From 9d42cad11f24513950801f46550b2d25b1870cfe Mon Sep 17 00:00:00 2001 From: defelmnq Date: Tue, 4 Feb 2025 23:32:48 +0000 Subject: [PATCH 01/32] work on new agent version --- agent/agent.go | 46 +- agent/agenttest/client.go | 30 +- agent/proto/agent.pb.go | 913 +++++++++++++++++++----- agent/proto/agent.proto | 35 + agent/proto/agent_drpc.pb.go | 82 ++- agent/proto/agent_drpc_old.go | 4 + coderd/agentapi/api.go | 3 + coderd/agentapi/resources_monitoring.go | 20 + codersdk/agentsdk/agentsdk.go | 12 + tailnet/proto/tailnet_drpc_old.go | 6 + tailnet/proto/version.go | 6 +- 11 files changed, 946 insertions(+), 211 deletions(-) create mode 100644 coderd/agentapi/resources_monitoring.go diff --git a/agent/agent.go b/agent/agent.go index 2daba701b4e89..a049ff83be0c4 100644 --- a/agent/agent.go +++ b/agent/agent.go @@ -85,8 +85,8 @@ type Options struct { } type Client interface { - ConnectRPC23(ctx context.Context) ( - proto.DRPCAgentClient23, tailnetproto.DRPCTailnetClient23, error, + ConnectRPC24(ctx context.Context) ( + proto.DRPCAgentClient24, tailnetproto.DRPCTailnetClient24, error, ) RewriteDERPMap(derpMap *tailcfg.DERPMap) } @@ -399,7 +399,7 @@ func (t *trySingleflight) Do(key string, fn func()) { fn() } -func (a *agent) reportMetadata(ctx context.Context, aAPI proto.DRPCAgentClient23) error { +func (a *agent) reportMetadata(ctx context.Context, aAPI proto.DRPCAgentClient24) error { tickerDone := make(chan struct{}) collectDone := make(chan struct{}) ctx, cancel := context.WithCancel(ctx) @@ -615,7 +615,7 @@ func (a *agent) reportMetadata(ctx context.Context, aAPI proto.DRPCAgentClient23 // reportLifecycle reports the current lifecycle state once. All state // changes are reported in order. -func (a *agent) reportLifecycle(ctx context.Context, aAPI proto.DRPCAgentClient23) error { +func (a *agent) reportLifecycle(ctx context.Context, aAPI proto.DRPCAgentClient24) error { for { select { case <-a.lifecycleUpdate: @@ -697,7 +697,7 @@ func (a *agent) setLifecycle(state codersdk.WorkspaceAgentLifecycle) { // fetchServiceBannerLoop fetches the service banner on an interval. It will // not be fetched immediately; the expectation is that it is primed elsewhere // (and must be done before the session actually starts). -func (a *agent) fetchServiceBannerLoop(ctx context.Context, aAPI proto.DRPCAgentClient23) error { +func (a *agent) fetchServiceBannerLoop(ctx context.Context, aAPI proto.DRPCAgentClient24) error { ticker := time.NewTicker(a.announcementBannersRefreshInterval) defer ticker.Stop() for { @@ -733,7 +733,7 @@ func (a *agent) run() (retErr error) { a.sessionToken.Store(&sessionToken) // ConnectRPC returns the dRPC connection we use for the Agent and Tailnet v2+ APIs - aAPI, tAPI, err := a.client.ConnectRPC23(a.hardCtx) + aAPI, tAPI, err := a.client.ConnectRPC24(a.hardCtx) if err != nil { return err } @@ -750,7 +750,7 @@ func (a *agent) run() (retErr error) { connMan := newAPIConnRoutineManager(a.gracefulCtx, a.hardCtx, a.logger, aAPI, tAPI) connMan.startAgentAPI("init notification banners", gracefulShutdownBehaviorStop, - func(ctx context.Context, aAPI proto.DRPCAgentClient23) error { + func(ctx context.Context, aAPI proto.DRPCAgentClient24) error { bannersProto, err := aAPI.GetAnnouncementBanners(ctx, &proto.GetAnnouncementBannersRequest{}) if err != nil { return xerrors.Errorf("fetch service banner: %w", err) @@ -767,7 +767,7 @@ func (a *agent) run() (retErr error) { // sending logs gets gracefulShutdownBehaviorRemain because we want to send logs generated by // shutdown scripts. connMan.startAgentAPI("send logs", gracefulShutdownBehaviorRemain, - func(ctx context.Context, aAPI proto.DRPCAgentClient23) error { + func(ctx context.Context, aAPI proto.DRPCAgentClient24) error { err := a.logSender.SendLoop(ctx, aAPI) if xerrors.Is(err, agentsdk.LogLimitExceededError) { // we don't want this error to tear down the API connection and propagate to the @@ -807,7 +807,7 @@ func (a *agent) run() (retErr error) { connMan.startAgentAPI("handle manifest", gracefulShutdownBehaviorStop, a.handleManifest(manifestOK)) connMan.startAgentAPI("app health reporter", gracefulShutdownBehaviorStop, - func(ctx context.Context, aAPI proto.DRPCAgentClient23) error { + func(ctx context.Context, aAPI proto.DRPCAgentClient24) error { if err := manifestOK.wait(ctx); err != nil { return xerrors.Errorf("no manifest: %w", err) } @@ -822,7 +822,7 @@ func (a *agent) run() (retErr error) { a.createOrUpdateNetwork(manifestOK, networkOK)) connMan.startTailnetAPI("coordination", gracefulShutdownBehaviorStop, - func(ctx context.Context, tAPI tailnetproto.DRPCTailnetClient23) error { + func(ctx context.Context, tAPI tailnetproto.DRPCTailnetClient24) error { if err := networkOK.wait(ctx); err != nil { return xerrors.Errorf("no network: %w", err) } @@ -831,7 +831,7 @@ func (a *agent) run() (retErr error) { ) connMan.startTailnetAPI("derp map subscriber", gracefulShutdownBehaviorStop, - func(ctx context.Context, tAPI tailnetproto.DRPCTailnetClient23) error { + func(ctx context.Context, tAPI tailnetproto.DRPCTailnetClient24) error { if err := networkOK.wait(ctx); err != nil { return xerrors.Errorf("no network: %w", err) } @@ -840,7 +840,7 @@ func (a *agent) run() (retErr error) { connMan.startAgentAPI("fetch service banner loop", gracefulShutdownBehaviorStop, a.fetchServiceBannerLoop) - connMan.startAgentAPI("stats report loop", gracefulShutdownBehaviorStop, func(ctx context.Context, aAPI proto.DRPCAgentClient23) error { + connMan.startAgentAPI("stats report loop", gracefulShutdownBehaviorStop, func(ctx context.Context, aAPI proto.DRPCAgentClient24) error { if err := networkOK.wait(ctx); err != nil { return xerrors.Errorf("no network: %w", err) } @@ -851,8 +851,8 @@ func (a *agent) run() (retErr error) { } // handleManifest returns a function that fetches and processes the manifest -func (a *agent) handleManifest(manifestOK *checkpoint) func(ctx context.Context, aAPI proto.DRPCAgentClient23) error { - return func(ctx context.Context, aAPI proto.DRPCAgentClient23) error { +func (a *agent) handleManifest(manifestOK *checkpoint) func(ctx context.Context, aAPI proto.DRPCAgentClient24) error { + return func(ctx context.Context, aAPI proto.DRPCAgentClient24) error { var ( sentResult = false err error @@ -961,8 +961,8 @@ func (a *agent) handleManifest(manifestOK *checkpoint) func(ctx context.Context, // createOrUpdateNetwork waits for the manifest to be set using manifestOK, then creates or updates // the tailnet using the information in the manifest -func (a *agent) createOrUpdateNetwork(manifestOK, networkOK *checkpoint) func(context.Context, proto.DRPCAgentClient23) error { - return func(ctx context.Context, _ proto.DRPCAgentClient23) (retErr error) { +func (a *agent) createOrUpdateNetwork(manifestOK, networkOK *checkpoint) func(context.Context, proto.DRPCAgentClient24) error { + return func(ctx context.Context, _ proto.DRPCAgentClient24) (retErr error) { if err := manifestOK.wait(ctx); err != nil { return xerrors.Errorf("no manifest: %w", err) } @@ -1266,7 +1266,7 @@ func (a *agent) createTailnet(ctx context.Context, agentID uuid.UUID, derpMap *t // runCoordinator runs a coordinator and returns whether a reconnect // should occur. -func (a *agent) runCoordinator(ctx context.Context, tClient tailnetproto.DRPCTailnetClient23, network *tailnet.Conn) error { +func (a *agent) runCoordinator(ctx context.Context, tClient tailnetproto.DRPCTailnetClient24, network *tailnet.Conn) error { defer a.logger.Debug(ctx, "disconnected from coordination RPC") // we run the RPC on the hardCtx so that we have a chance to send the disconnect message if we // gracefully shut down. @@ -1313,7 +1313,7 @@ func (a *agent) runCoordinator(ctx context.Context, tClient tailnetproto.DRPCTai } // runDERPMapSubscriber runs a coordinator and returns if a reconnect should occur. -func (a *agent) runDERPMapSubscriber(ctx context.Context, tClient tailnetproto.DRPCTailnetClient23, network *tailnet.Conn) error { +func (a *agent) runDERPMapSubscriber(ctx context.Context, tClient tailnetproto.DRPCTailnetClient24, network *tailnet.Conn) error { defer a.logger.Debug(ctx, "disconnected from derp map RPC") ctx, cancel := context.WithCancel(ctx) defer cancel() @@ -1683,8 +1683,8 @@ const ( type apiConnRoutineManager struct { logger slog.Logger - aAPI proto.DRPCAgentClient23 - tAPI tailnetproto.DRPCTailnetClient23 + aAPI proto.DRPCAgentClient24 + tAPI tailnetproto.DRPCTailnetClient24 eg *errgroup.Group stopCtx context.Context remainCtx context.Context @@ -1692,7 +1692,7 @@ type apiConnRoutineManager struct { func newAPIConnRoutineManager( gracefulCtx, hardCtx context.Context, logger slog.Logger, - aAPI proto.DRPCAgentClient23, tAPI tailnetproto.DRPCTailnetClient23, + aAPI proto.DRPCAgentClient24, tAPI tailnetproto.DRPCTailnetClient24, ) *apiConnRoutineManager { // routines that remain in operation during graceful shutdown use the remainCtx. They'll still // exit if the errgroup hits an error, which usually means a problem with the conn. @@ -1725,7 +1725,7 @@ func newAPIConnRoutineManager( // but for Tailnet. func (a *apiConnRoutineManager) startAgentAPI( name string, behavior gracefulShutdownBehavior, - f func(context.Context, proto.DRPCAgentClient23) error, + f func(context.Context, proto.DRPCAgentClient24) error, ) { logger := a.logger.With(slog.F("name", name)) var ctx context.Context @@ -1762,7 +1762,7 @@ func (a *apiConnRoutineManager) startAgentAPI( // but for the Agent API. func (a *apiConnRoutineManager) startTailnetAPI( name string, behavior gracefulShutdownBehavior, - f func(context.Context, tailnetproto.DRPCTailnetClient23) error, + f func(context.Context, tailnetproto.DRPCTailnetClient24) error, ) { logger := a.logger.With(slog.F("name", name)) var ctx context.Context diff --git a/agent/agenttest/client.go b/agent/agenttest/client.go index 6b2581e7831f2..e07cf1a2732ab 100644 --- a/agent/agenttest/client.go +++ b/agent/agenttest/client.go @@ -96,8 +96,8 @@ func (c *Client) Close() { c.derpMapOnce.Do(func() { close(c.derpMapUpdates) }) } -func (c *Client) ConnectRPC23(ctx context.Context) ( - agentproto.DRPCAgentClient23, proto.DRPCTailnetClient23, error, +func (c *Client) ConnectRPC24(ctx context.Context) ( + agentproto.DRPCAgentClient24, proto.DRPCTailnetClient24, error, ) { conn, lis := drpcsdk.MemTransportPipe() c.LastWorkspaceAgent = func() { @@ -171,7 +171,9 @@ type FakeAgentAPI struct { metadata map[string]agentsdk.Metadata timings []*agentproto.Timing - getAnnouncementBannersFunc func() ([]codersdk.BannerConfig, error) + getAnnouncementBannersFunc func() ([]codersdk.BannerConfig, error) + getResourcesMonitoringConfigurationFunc func() (*agentproto.GetResourcesMonitoringConfigurationResponse, error) + pushResourcesMonitoringUsageFunc func(*agentproto.PushResourcesMonitoringUsageRequest) (*agentproto.PushResourcesMonitoringUsageResponse, error) } func (f *FakeAgentAPI) GetManifest(context.Context, *agentproto.GetManifestRequest) (*agentproto.Manifest, error) { @@ -212,6 +214,28 @@ func (f *FakeAgentAPI) GetAnnouncementBanners(context.Context, *agentproto.GetAn return &agentproto.GetAnnouncementBannersResponse{AnnouncementBanners: bannersProto}, nil } +func (f *FakeAgentAPI) GetResourcesMonitoringConfiguration(ctx context.Context, req *agentproto.GetResourcesMonitoringConfigurationRequest) (*agentproto.GetResourcesMonitoringConfigurationResponse, error) { + f.Lock() + defer f.Unlock() + + if f.getResourcesMonitoringConfigurationFunc == nil { + return nil, xerrors.Errorf("GetResourcesMonitoringConfiguration is not implemented") + } + + return f.getResourcesMonitoringConfigurationFunc() +} + +func (f *FakeAgentAPI) PushResourcesMonitoringUsage(ctx context.Context, req *agentproto.PushResourcesMonitoringUsageRequest) (*agentproto.PushResourcesMonitoringUsageResponse, error) { + f.Lock() + defer f.Unlock() + + if f.pushResourcesMonitoringUsageFunc == nil { + return nil, xerrors.Errorf("PushResourcesMonitoringUsage is not implemented") + } + + return f.pushResourcesMonitoringUsageFunc(req) +} + func (f *FakeAgentAPI) UpdateStats(ctx context.Context, req *agentproto.UpdateStatsRequest) (*agentproto.UpdateStatsResponse, error) { f.logger.Debug(ctx, "update stats called", slog.F("req", req)) // empty request is sent to get the interval; but our tests don't want empty stats requests diff --git a/agent/proto/agent.pb.go b/agent/proto/agent.pb.go index 4b90e0cf60736..69dbcc5597590 100644 --- a/agent/proto/agent.pb.go +++ b/agent/proto/agent.pb.go @@ -2304,6 +2304,192 @@ func (x *Timing) GetStatus() Timing_Status { return Timing_OK } +type GetResourcesMonitoringConfigurationRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *GetResourcesMonitoringConfigurationRequest) Reset() { + *x = GetResourcesMonitoringConfigurationRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_agent_proto_agent_proto_msgTypes[28] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetResourcesMonitoringConfigurationRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetResourcesMonitoringConfigurationRequest) ProtoMessage() {} + +func (x *GetResourcesMonitoringConfigurationRequest) ProtoReflect() protoreflect.Message { + mi := &file_agent_proto_agent_proto_msgTypes[28] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetResourcesMonitoringConfigurationRequest.ProtoReflect.Descriptor instead. +func (*GetResourcesMonitoringConfigurationRequest) Descriptor() ([]byte, []int) { + return file_agent_proto_agent_proto_rawDescGZIP(), []int{28} +} + +type GetResourcesMonitoringConfigurationResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Enabled bool `protobuf:"varint,1,opt,name=enabled,proto3" json:"enabled,omitempty"` + Config *GetResourcesMonitoringConfigurationResponse_Config `protobuf:"bytes,2,opt,name=config,proto3" json:"config,omitempty"` + MonitoredVolumes []string `protobuf:"bytes,3,rep,name=monitored_volumes,json=monitoredVolumes,proto3" json:"monitored_volumes,omitempty"` +} + +func (x *GetResourcesMonitoringConfigurationResponse) Reset() { + *x = GetResourcesMonitoringConfigurationResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_agent_proto_agent_proto_msgTypes[29] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetResourcesMonitoringConfigurationResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetResourcesMonitoringConfigurationResponse) ProtoMessage() {} + +func (x *GetResourcesMonitoringConfigurationResponse) ProtoReflect() protoreflect.Message { + mi := &file_agent_proto_agent_proto_msgTypes[29] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetResourcesMonitoringConfigurationResponse.ProtoReflect.Descriptor instead. +func (*GetResourcesMonitoringConfigurationResponse) Descriptor() ([]byte, []int) { + return file_agent_proto_agent_proto_rawDescGZIP(), []int{29} +} + +func (x *GetResourcesMonitoringConfigurationResponse) GetEnabled() bool { + if x != nil { + return x.Enabled + } + return false +} + +func (x *GetResourcesMonitoringConfigurationResponse) GetConfig() *GetResourcesMonitoringConfigurationResponse_Config { + if x != nil { + return x.Config + } + return nil +} + +func (x *GetResourcesMonitoringConfigurationResponse) GetMonitoredVolumes() []string { + if x != nil { + return x.MonitoredVolumes + } + return nil +} + +type PushResourcesMonitoringUsageRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Datapoints []*PushResourcesMonitoringUsageRequest_Datapoint `protobuf:"bytes,1,rep,name=datapoints,proto3" json:"datapoints,omitempty"` +} + +func (x *PushResourcesMonitoringUsageRequest) Reset() { + *x = PushResourcesMonitoringUsageRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_agent_proto_agent_proto_msgTypes[30] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PushResourcesMonitoringUsageRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PushResourcesMonitoringUsageRequest) ProtoMessage() {} + +func (x *PushResourcesMonitoringUsageRequest) ProtoReflect() protoreflect.Message { + mi := &file_agent_proto_agent_proto_msgTypes[30] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PushResourcesMonitoringUsageRequest.ProtoReflect.Descriptor instead. +func (*PushResourcesMonitoringUsageRequest) Descriptor() ([]byte, []int) { + return file_agent_proto_agent_proto_rawDescGZIP(), []int{30} +} + +func (x *PushResourcesMonitoringUsageRequest) GetDatapoints() []*PushResourcesMonitoringUsageRequest_Datapoint { + if x != nil { + return x.Datapoints + } + return nil +} + +type PushResourcesMonitoringUsageResponse struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields +} + +func (x *PushResourcesMonitoringUsageResponse) Reset() { + *x = PushResourcesMonitoringUsageResponse{} + if protoimpl.UnsafeEnabled { + mi := &file_agent_proto_agent_proto_msgTypes[31] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PushResourcesMonitoringUsageResponse) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PushResourcesMonitoringUsageResponse) ProtoMessage() {} + +func (x *PushResourcesMonitoringUsageResponse) ProtoReflect() protoreflect.Message { + mi := &file_agent_proto_agent_proto_msgTypes[31] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PushResourcesMonitoringUsageResponse.ProtoReflect.Descriptor instead. +func (*PushResourcesMonitoringUsageResponse) Descriptor() ([]byte, []int) { + return file_agent_proto_agent_proto_rawDescGZIP(), []int{31} +} + type WorkspaceApp_Healthcheck struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -2317,7 +2503,7 @@ type WorkspaceApp_Healthcheck struct { func (x *WorkspaceApp_Healthcheck) Reset() { *x = WorkspaceApp_Healthcheck{} if protoimpl.UnsafeEnabled { - mi := &file_agent_proto_agent_proto_msgTypes[28] + mi := &file_agent_proto_agent_proto_msgTypes[32] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2330,7 +2516,7 @@ func (x *WorkspaceApp_Healthcheck) String() string { func (*WorkspaceApp_Healthcheck) ProtoMessage() {} func (x *WorkspaceApp_Healthcheck) ProtoReflect() protoreflect.Message { - mi := &file_agent_proto_agent_proto_msgTypes[28] + mi := &file_agent_proto_agent_proto_msgTypes[32] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2381,7 +2567,7 @@ type WorkspaceAgentMetadata_Result struct { func (x *WorkspaceAgentMetadata_Result) Reset() { *x = WorkspaceAgentMetadata_Result{} if protoimpl.UnsafeEnabled { - mi := &file_agent_proto_agent_proto_msgTypes[29] + mi := &file_agent_proto_agent_proto_msgTypes[33] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2394,7 +2580,7 @@ func (x *WorkspaceAgentMetadata_Result) String() string { func (*WorkspaceAgentMetadata_Result) ProtoMessage() {} func (x *WorkspaceAgentMetadata_Result) ProtoReflect() protoreflect.Message { - mi := &file_agent_proto_agent_proto_msgTypes[29] + mi := &file_agent_proto_agent_proto_msgTypes[33] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2453,7 +2639,7 @@ type WorkspaceAgentMetadata_Description struct { func (x *WorkspaceAgentMetadata_Description) Reset() { *x = WorkspaceAgentMetadata_Description{} if protoimpl.UnsafeEnabled { - mi := &file_agent_proto_agent_proto_msgTypes[30] + mi := &file_agent_proto_agent_proto_msgTypes[34] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2466,7 +2652,7 @@ func (x *WorkspaceAgentMetadata_Description) String() string { func (*WorkspaceAgentMetadata_Description) ProtoMessage() {} func (x *WorkspaceAgentMetadata_Description) ProtoReflect() protoreflect.Message { - mi := &file_agent_proto_agent_proto_msgTypes[30] + mi := &file_agent_proto_agent_proto_msgTypes[34] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2531,7 +2717,7 @@ type Stats_Metric struct { func (x *Stats_Metric) Reset() { *x = Stats_Metric{} if protoimpl.UnsafeEnabled { - mi := &file_agent_proto_agent_proto_msgTypes[33] + mi := &file_agent_proto_agent_proto_msgTypes[37] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2544,7 +2730,7 @@ func (x *Stats_Metric) String() string { func (*Stats_Metric) ProtoMessage() {} func (x *Stats_Metric) ProtoReflect() protoreflect.Message { - mi := &file_agent_proto_agent_proto_msgTypes[33] + mi := &file_agent_proto_agent_proto_msgTypes[37] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2600,7 +2786,7 @@ type Stats_Metric_Label struct { func (x *Stats_Metric_Label) Reset() { *x = Stats_Metric_Label{} if protoimpl.UnsafeEnabled { - mi := &file_agent_proto_agent_proto_msgTypes[34] + mi := &file_agent_proto_agent_proto_msgTypes[38] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2613,7 +2799,7 @@ func (x *Stats_Metric_Label) String() string { func (*Stats_Metric_Label) ProtoMessage() {} func (x *Stats_Metric_Label) ProtoReflect() protoreflect.Message { - mi := &file_agent_proto_agent_proto_msgTypes[34] + mi := &file_agent_proto_agent_proto_msgTypes[38] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2655,7 +2841,7 @@ type BatchUpdateAppHealthRequest_HealthUpdate struct { func (x *BatchUpdateAppHealthRequest_HealthUpdate) Reset() { *x = BatchUpdateAppHealthRequest_HealthUpdate{} if protoimpl.UnsafeEnabled { - mi := &file_agent_proto_agent_proto_msgTypes[35] + mi := &file_agent_proto_agent_proto_msgTypes[39] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2668,7 +2854,7 @@ func (x *BatchUpdateAppHealthRequest_HealthUpdate) String() string { func (*BatchUpdateAppHealthRequest_HealthUpdate) ProtoMessage() {} func (x *BatchUpdateAppHealthRequest_HealthUpdate) ProtoReflect() protoreflect.Message { - mi := &file_agent_proto_agent_proto_msgTypes[35] + mi := &file_agent_proto_agent_proto_msgTypes[39] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -2698,6 +2884,195 @@ func (x *BatchUpdateAppHealthRequest_HealthUpdate) GetHealth() AppHealth { return AppHealth_APP_HEALTH_UNSPECIFIED } +type GetResourcesMonitoringConfigurationResponse_Config struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + NumDatapoints int32 `protobuf:"varint,1,opt,name=num_datapoints,json=numDatapoints,proto3" json:"num_datapoints,omitempty"` + TickInterval int32 `protobuf:"varint,2,opt,name=tick_interval,json=tickInterval,proto3" json:"tick_interval,omitempty"` // expressed in seconds +} + +func (x *GetResourcesMonitoringConfigurationResponse_Config) Reset() { + *x = GetResourcesMonitoringConfigurationResponse_Config{} + if protoimpl.UnsafeEnabled { + mi := &file_agent_proto_agent_proto_msgTypes[40] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetResourcesMonitoringConfigurationResponse_Config) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetResourcesMonitoringConfigurationResponse_Config) ProtoMessage() {} + +func (x *GetResourcesMonitoringConfigurationResponse_Config) ProtoReflect() protoreflect.Message { + mi := &file_agent_proto_agent_proto_msgTypes[40] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetResourcesMonitoringConfigurationResponse_Config.ProtoReflect.Descriptor instead. +func (*GetResourcesMonitoringConfigurationResponse_Config) Descriptor() ([]byte, []int) { + return file_agent_proto_agent_proto_rawDescGZIP(), []int{29, 0} +} + +func (x *GetResourcesMonitoringConfigurationResponse_Config) GetNumDatapoints() int32 { + if x != nil { + return x.NumDatapoints + } + return 0 +} + +func (x *GetResourcesMonitoringConfigurationResponse_Config) GetTickInterval() int32 { + if x != nil { + return x.TickInterval + } + return 0 +} + +type PushResourcesMonitoringUsageRequest_Datapoint struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + CollectedAt *timestamppb.Timestamp `protobuf:"bytes,1,opt,name=collected_at,json=collectedAt,proto3" json:"collected_at,omitempty"` + MemoryUsed int32 `protobuf:"varint,2,opt,name=memory_used,json=memoryUsed,proto3" json:"memory_used,omitempty"` + MemoryTotal int32 `protobuf:"varint,3,opt,name=memory_total,json=memoryTotal,proto3" json:"memory_total,omitempty"` + Volumes []*PushResourcesMonitoringUsageRequest_Datapoint_VolumeUsage `protobuf:"bytes,4,rep,name=volumes,proto3" json:"volumes,omitempty"` +} + +func (x *PushResourcesMonitoringUsageRequest_Datapoint) Reset() { + *x = PushResourcesMonitoringUsageRequest_Datapoint{} + if protoimpl.UnsafeEnabled { + mi := &file_agent_proto_agent_proto_msgTypes[41] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PushResourcesMonitoringUsageRequest_Datapoint) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PushResourcesMonitoringUsageRequest_Datapoint) ProtoMessage() {} + +func (x *PushResourcesMonitoringUsageRequest_Datapoint) ProtoReflect() protoreflect.Message { + mi := &file_agent_proto_agent_proto_msgTypes[41] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PushResourcesMonitoringUsageRequest_Datapoint.ProtoReflect.Descriptor instead. +func (*PushResourcesMonitoringUsageRequest_Datapoint) Descriptor() ([]byte, []int) { + return file_agent_proto_agent_proto_rawDescGZIP(), []int{30, 0} +} + +func (x *PushResourcesMonitoringUsageRequest_Datapoint) GetCollectedAt() *timestamppb.Timestamp { + if x != nil { + return x.CollectedAt + } + return nil +} + +func (x *PushResourcesMonitoringUsageRequest_Datapoint) GetMemoryUsed() int32 { + if x != nil { + return x.MemoryUsed + } + return 0 +} + +func (x *PushResourcesMonitoringUsageRequest_Datapoint) GetMemoryTotal() int32 { + if x != nil { + return x.MemoryTotal + } + return 0 +} + +func (x *PushResourcesMonitoringUsageRequest_Datapoint) GetVolumes() []*PushResourcesMonitoringUsageRequest_Datapoint_VolumeUsage { + if x != nil { + return x.Volumes + } + return nil +} + +type PushResourcesMonitoringUsageRequest_Datapoint_VolumeUsage struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Volume string `protobuf:"bytes,1,opt,name=volume,proto3" json:"volume,omitempty"` + SpaceUsed int32 `protobuf:"varint,2,opt,name=space_used,json=spaceUsed,proto3" json:"space_used,omitempty"` + SpaceTotal int32 `protobuf:"varint,3,opt,name=space_total,json=spaceTotal,proto3" json:"space_total,omitempty"` +} + +func (x *PushResourcesMonitoringUsageRequest_Datapoint_VolumeUsage) Reset() { + *x = PushResourcesMonitoringUsageRequest_Datapoint_VolumeUsage{} + if protoimpl.UnsafeEnabled { + mi := &file_agent_proto_agent_proto_msgTypes[42] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PushResourcesMonitoringUsageRequest_Datapoint_VolumeUsage) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PushResourcesMonitoringUsageRequest_Datapoint_VolumeUsage) ProtoMessage() {} + +func (x *PushResourcesMonitoringUsageRequest_Datapoint_VolumeUsage) ProtoReflect() protoreflect.Message { + mi := &file_agent_proto_agent_proto_msgTypes[42] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PushResourcesMonitoringUsageRequest_Datapoint_VolumeUsage.ProtoReflect.Descriptor instead. +func (*PushResourcesMonitoringUsageRequest_Datapoint_VolumeUsage) Descriptor() ([]byte, []int) { + return file_agent_proto_agent_proto_rawDescGZIP(), []int{30, 0, 0} +} + +func (x *PushResourcesMonitoringUsageRequest_Datapoint_VolumeUsage) GetVolume() string { + if x != nil { + return x.Volume + } + return "" +} + +func (x *PushResourcesMonitoringUsageRequest_Datapoint_VolumeUsage) GetSpaceUsed() int32 { + if x != nil { + return x.SpaceUsed + } + return 0 +} + +func (x *PushResourcesMonitoringUsageRequest_Datapoint_VolumeUsage) GetSpaceTotal() int32 { + if x != nil { + return x.SpaceTotal + } + return 0 +} + var File_agent_proto_agent_proto protoreflect.FileDescriptor var file_agent_proto_agent_proto_rawDesc = []byte{ @@ -3092,76 +3467,149 @@ var file_agent_proto_agent_proto_rawDesc = []byte{ 0x0c, 0x45, 0x58, 0x49, 0x54, 0x5f, 0x46, 0x41, 0x49, 0x4c, 0x55, 0x52, 0x45, 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x54, 0x49, 0x4d, 0x45, 0x44, 0x5f, 0x4f, 0x55, 0x54, 0x10, 0x02, 0x12, 0x13, 0x0a, 0x0f, 0x50, 0x49, 0x50, 0x45, 0x53, 0x5f, 0x4c, 0x45, 0x46, 0x54, 0x5f, 0x4f, 0x50, 0x45, - 0x4e, 0x10, 0x03, 0x2a, 0x63, 0x0a, 0x09, 0x41, 0x70, 0x70, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, - 0x12, 0x1a, 0x0a, 0x16, 0x41, 0x50, 0x50, 0x5f, 0x48, 0x45, 0x41, 0x4c, 0x54, 0x48, 0x5f, 0x55, - 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0c, 0x0a, 0x08, - 0x44, 0x49, 0x53, 0x41, 0x42, 0x4c, 0x45, 0x44, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x49, 0x4e, - 0x49, 0x54, 0x49, 0x41, 0x4c, 0x49, 0x5a, 0x49, 0x4e, 0x47, 0x10, 0x02, 0x12, 0x0b, 0x0a, 0x07, - 0x48, 0x45, 0x41, 0x4c, 0x54, 0x48, 0x59, 0x10, 0x03, 0x12, 0x0d, 0x0a, 0x09, 0x55, 0x4e, 0x48, - 0x45, 0x41, 0x4c, 0x54, 0x48, 0x59, 0x10, 0x04, 0x32, 0xef, 0x07, 0x0a, 0x05, 0x41, 0x67, 0x65, - 0x6e, 0x74, 0x12, 0x4b, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x4d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, - 0x74, 0x12, 0x22, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, - 0x76, 0x32, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, - 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x4d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x12, - 0x5a, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x42, 0x61, 0x6e, - 0x6e, 0x65, 0x72, 0x12, 0x27, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, - 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x42, - 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x63, - 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x53, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x42, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x12, 0x56, 0x0a, 0x0b, 0x55, - 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x22, 0x2e, 0x63, 0x6f, 0x64, - 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x55, 0x70, 0x64, 0x61, - 0x74, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, - 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, - 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x0f, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x66, - 0x65, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x12, 0x26, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, - 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4c, 0x69, - 0x66, 0x65, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, - 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, - 0x4c, 0x69, 0x66, 0x65, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x12, 0x72, 0x0a, 0x15, 0x42, 0x61, 0x74, - 0x63, 0x68, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x70, 0x70, 0x48, 0x65, 0x61, 0x6c, 0x74, - 0x68, 0x73, 0x12, 0x2b, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, + 0x4e, 0x10, 0x03, 0x22, 0x2c, 0x0a, 0x2a, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x73, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x22, 0xa6, 0x02, 0x0a, 0x2b, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x73, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, + 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x5a, 0x0a, 0x06, 0x63, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x42, 0x2e, 0x63, 0x6f, + 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x47, 0x65, 0x74, + 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, + 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, + 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x2b, 0x0a, 0x11, 0x6d, 0x6f, 0x6e, 0x69, 0x74, + 0x6f, 0x72, 0x65, 0x64, 0x5f, 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, + 0x28, 0x09, 0x52, 0x10, 0x6d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x65, 0x64, 0x56, 0x6f, 0x6c, + 0x75, 0x6d, 0x65, 0x73, 0x1a, 0x54, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x25, + 0x0a, 0x0e, 0x6e, 0x75, 0x6d, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x6e, 0x75, 0x6d, 0x44, 0x61, 0x74, 0x61, 0x70, + 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x74, 0x69, 0x63, 0x6b, 0x5f, 0x69, 0x6e, + 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x74, 0x69, + 0x63, 0x6b, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x22, 0xe1, 0x03, 0x0a, 0x23, 0x50, + 0x75, 0x73, 0x68, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x4d, 0x6f, 0x6e, 0x69, + 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x12, 0x5d, 0x0a, 0x0a, 0x64, 0x61, 0x74, 0x61, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, + 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3d, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, + 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x50, 0x75, 0x73, 0x68, 0x52, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x73, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x55, + 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x44, 0x61, 0x74, 0x61, + 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x0a, 0x64, 0x61, 0x74, 0x61, 0x70, 0x6f, 0x69, 0x6e, 0x74, + 0x73, 0x1a, 0xda, 0x02, 0x0a, 0x09, 0x44, 0x61, 0x74, 0x61, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, + 0x3d, 0x0a, 0x0c, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, + 0x70, 0x52, 0x0b, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x1f, + 0x0a, 0x0b, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x5f, 0x75, 0x73, 0x65, 0x64, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x05, 0x52, 0x0a, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x55, 0x73, 0x65, 0x64, 0x12, + 0x21, 0x0a, 0x0c, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x5f, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x54, 0x6f, 0x74, + 0x61, 0x6c, 0x12, 0x63, 0x0a, 0x07, 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x73, 0x18, 0x04, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x49, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, + 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x50, 0x75, 0x73, 0x68, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x73, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x55, 0x73, 0x61, 0x67, + 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x70, 0x6f, 0x69, + 0x6e, 0x74, 0x2e, 0x56, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x07, + 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x73, 0x1a, 0x65, 0x0a, 0x0b, 0x56, 0x6f, 0x6c, 0x75, 0x6d, + 0x65, 0x55, 0x73, 0x61, 0x67, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x12, 0x1d, + 0x0a, 0x0a, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x75, 0x73, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x05, 0x52, 0x09, 0x73, 0x70, 0x61, 0x63, 0x65, 0x55, 0x73, 0x65, 0x64, 0x12, 0x1f, 0x0a, + 0x0b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x05, 0x52, 0x0a, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x6f, 0x74, 0x61, 0x6c, 0x22, 0x26, + 0x0a, 0x24, 0x50, 0x75, 0x73, 0x68, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x4d, + 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2a, 0x63, 0x0a, 0x09, 0x41, 0x70, 0x70, 0x48, 0x65, 0x61, + 0x6c, 0x74, 0x68, 0x12, 0x1a, 0x0a, 0x16, 0x41, 0x50, 0x50, 0x5f, 0x48, 0x45, 0x41, 0x4c, 0x54, + 0x48, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, + 0x0c, 0x0a, 0x08, 0x44, 0x49, 0x53, 0x41, 0x42, 0x4c, 0x45, 0x44, 0x10, 0x01, 0x12, 0x10, 0x0a, + 0x0c, 0x49, 0x4e, 0x49, 0x54, 0x49, 0x41, 0x4c, 0x49, 0x5a, 0x49, 0x4e, 0x47, 0x10, 0x02, 0x12, + 0x0b, 0x0a, 0x07, 0x48, 0x45, 0x41, 0x4c, 0x54, 0x48, 0x59, 0x10, 0x03, 0x12, 0x0d, 0x0a, 0x09, + 0x55, 0x4e, 0x48, 0x45, 0x41, 0x4c, 0x54, 0x48, 0x59, 0x10, 0x04, 0x32, 0x9c, 0x0a, 0x0a, 0x05, + 0x41, 0x67, 0x65, 0x6e, 0x74, 0x12, 0x4b, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x4d, 0x61, 0x6e, 0x69, + 0x66, 0x65, 0x73, 0x74, 0x12, 0x22, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, + 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, + 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, + 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x4d, 0x61, 0x6e, 0x69, 0x66, 0x65, + 0x73, 0x74, 0x12, 0x5a, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, + 0x42, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x12, 0x27, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, + 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x42, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x1d, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, + 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x42, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x12, 0x56, + 0x0a, 0x0b, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x22, 0x2e, + 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x55, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x23, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, + 0x76, 0x32, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x0f, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, + 0x4c, 0x69, 0x66, 0x65, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x12, 0x26, 0x2e, 0x63, 0x6f, 0x64, 0x65, + 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x4c, 0x69, 0x66, 0x65, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x19, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, + 0x76, 0x32, 0x2e, 0x4c, 0x69, 0x66, 0x65, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x12, 0x72, 0x0a, 0x15, + 0x42, 0x61, 0x74, 0x63, 0x68, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x70, 0x70, 0x48, 0x65, + 0x61, 0x6c, 0x74, 0x68, 0x73, 0x12, 0x2b, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, + 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x55, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x41, 0x70, 0x70, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, - 0x70, 0x70, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x2c, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, - 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x70, 0x70, 0x48, - 0x65, 0x61, 0x6c, 0x74, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4e, 0x0a, - 0x0d, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x12, 0x24, + 0x70, 0x70, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x4e, 0x0a, 0x0d, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x74, 0x61, 0x72, 0x74, 0x75, + 0x70, 0x12, 0x24, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, + 0x76, 0x32, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, + 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, + 0x12, 0x6e, 0x0a, 0x13, 0x42, 0x61, 0x74, 0x63, 0x68, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, + 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x2a, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, + 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x55, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, + 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, + 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x62, 0x0a, 0x0f, 0x42, 0x61, 0x74, 0x63, 0x68, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4c, + 0x6f, 0x67, 0x73, 0x12, 0x26, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, + 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, + 0x4c, 0x6f, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x63, 0x6f, + 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x61, 0x74, + 0x63, 0x68, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4c, 0x6f, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70, + 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x77, 0x0a, 0x16, 0x47, 0x65, 0x74, 0x41, 0x6e, 0x6e, 0x6f, 0x75, + 0x6e, 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x42, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x73, 0x12, 0x2d, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, - 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, - 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x12, 0x6e, 0x0a, - 0x13, 0x42, 0x61, 0x74, 0x63, 0x68, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x74, 0x61, - 0x64, 0x61, 0x74, 0x61, 0x12, 0x2a, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, - 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x55, 0x70, 0x64, 0x61, 0x74, - 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x2b, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, - 0x32, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x74, - 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x62, 0x0a, - 0x0f, 0x42, 0x61, 0x74, 0x63, 0x68, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4c, 0x6f, 0x67, 0x73, - 0x12, 0x26, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, - 0x32, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4c, 0x6f, 0x67, - 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, - 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x43, - 0x72, 0x65, 0x61, 0x74, 0x65, 0x4c, 0x6f, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x77, 0x0a, 0x16, 0x47, 0x65, 0x74, 0x41, 0x6e, 0x6e, 0x6f, 0x75, 0x6e, 0x63, 0x65, - 0x6d, 0x65, 0x6e, 0x74, 0x42, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x73, 0x12, 0x2d, 0x2e, 0x63, 0x6f, - 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x47, 0x65, 0x74, - 0x41, 0x6e, 0x6e, 0x6f, 0x75, 0x6e, 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x42, 0x61, 0x6e, 0x6e, - 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x63, 0x6f, 0x64, - 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x47, 0x65, 0x74, 0x41, - 0x6e, 0x6e, 0x6f, 0x75, 0x6e, 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x42, 0x61, 0x6e, 0x6e, 0x65, - 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x7e, 0x0a, 0x0f, 0x53, 0x63, - 0x72, 0x69, 0x70, 0x74, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x12, 0x34, 0x2e, - 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x57, - 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x53, 0x63, 0x72, - 0x69, 0x70, 0x74, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, - 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x41, 0x67, - 0x65, 0x6e, 0x74, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, - 0x65, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x27, 0x5a, 0x25, 0x67, 0x69, + 0x47, 0x65, 0x74, 0x41, 0x6e, 0x6e, 0x6f, 0x75, 0x6e, 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x42, + 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, + 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x47, + 0x65, 0x74, 0x41, 0x6e, 0x6e, 0x6f, 0x75, 0x6e, 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x42, 0x61, + 0x6e, 0x6e, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x7e, 0x0a, + 0x0f, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x64, + 0x12, 0x34, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, + 0x32, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x41, 0x67, 0x65, 0x6e, 0x74, + 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, + 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, + 0x65, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x43, 0x6f, 0x6d, 0x70, + 0x6c, 0x65, 0x74, 0x65, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x9e, 0x01, + 0x0a, 0x23, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x4d, 0x6f, + 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x3a, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, + 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x73, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, + 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x3b, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, + 0x76, 0x32, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x4d, + 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, + 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x89, + 0x01, 0x0a, 0x1c, 0x50, 0x75, 0x73, 0x68, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, + 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x55, 0x73, 0x61, 0x67, 0x65, 0x12, + 0x33, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, + 0x2e, 0x50, 0x75, 0x73, 0x68, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x4d, 0x6f, + 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, + 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x50, 0x75, 0x73, 0x68, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x73, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x55, 0x73, 0x61, + 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x27, 0x5a, 0x25, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2f, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2f, 0x76, 0x32, 0x2f, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, @@ -3180,122 +3628,137 @@ func file_agent_proto_agent_proto_rawDescGZIP() []byte { } var file_agent_proto_agent_proto_enumTypes = make([]protoimpl.EnumInfo, 9) -var file_agent_proto_agent_proto_msgTypes = make([]protoimpl.MessageInfo, 36) +var file_agent_proto_agent_proto_msgTypes = make([]protoimpl.MessageInfo, 43) var file_agent_proto_agent_proto_goTypes = []interface{}{ - (AppHealth)(0), // 0: coder.agent.v2.AppHealth - (WorkspaceApp_SharingLevel)(0), // 1: coder.agent.v2.WorkspaceApp.SharingLevel - (WorkspaceApp_Health)(0), // 2: coder.agent.v2.WorkspaceApp.Health - (Stats_Metric_Type)(0), // 3: coder.agent.v2.Stats.Metric.Type - (Lifecycle_State)(0), // 4: coder.agent.v2.Lifecycle.State - (Startup_Subsystem)(0), // 5: coder.agent.v2.Startup.Subsystem - (Log_Level)(0), // 6: coder.agent.v2.Log.Level - (Timing_Stage)(0), // 7: coder.agent.v2.Timing.Stage - (Timing_Status)(0), // 8: coder.agent.v2.Timing.Status - (*WorkspaceApp)(nil), // 9: coder.agent.v2.WorkspaceApp - (*WorkspaceAgentScript)(nil), // 10: coder.agent.v2.WorkspaceAgentScript - (*WorkspaceAgentMetadata)(nil), // 11: coder.agent.v2.WorkspaceAgentMetadata - (*Manifest)(nil), // 12: coder.agent.v2.Manifest - (*GetManifestRequest)(nil), // 13: coder.agent.v2.GetManifestRequest - (*ServiceBanner)(nil), // 14: coder.agent.v2.ServiceBanner - (*GetServiceBannerRequest)(nil), // 15: coder.agent.v2.GetServiceBannerRequest - (*Stats)(nil), // 16: coder.agent.v2.Stats - (*UpdateStatsRequest)(nil), // 17: coder.agent.v2.UpdateStatsRequest - (*UpdateStatsResponse)(nil), // 18: coder.agent.v2.UpdateStatsResponse - (*Lifecycle)(nil), // 19: coder.agent.v2.Lifecycle - (*UpdateLifecycleRequest)(nil), // 20: coder.agent.v2.UpdateLifecycleRequest - (*BatchUpdateAppHealthRequest)(nil), // 21: coder.agent.v2.BatchUpdateAppHealthRequest - (*BatchUpdateAppHealthResponse)(nil), // 22: coder.agent.v2.BatchUpdateAppHealthResponse - (*Startup)(nil), // 23: coder.agent.v2.Startup - (*UpdateStartupRequest)(nil), // 24: coder.agent.v2.UpdateStartupRequest - (*Metadata)(nil), // 25: coder.agent.v2.Metadata - (*BatchUpdateMetadataRequest)(nil), // 26: coder.agent.v2.BatchUpdateMetadataRequest - (*BatchUpdateMetadataResponse)(nil), // 27: coder.agent.v2.BatchUpdateMetadataResponse - (*Log)(nil), // 28: coder.agent.v2.Log - (*BatchCreateLogsRequest)(nil), // 29: coder.agent.v2.BatchCreateLogsRequest - (*BatchCreateLogsResponse)(nil), // 30: coder.agent.v2.BatchCreateLogsResponse - (*GetAnnouncementBannersRequest)(nil), // 31: coder.agent.v2.GetAnnouncementBannersRequest - (*GetAnnouncementBannersResponse)(nil), // 32: coder.agent.v2.GetAnnouncementBannersResponse - (*BannerConfig)(nil), // 33: coder.agent.v2.BannerConfig - (*WorkspaceAgentScriptCompletedRequest)(nil), // 34: coder.agent.v2.WorkspaceAgentScriptCompletedRequest - (*WorkspaceAgentScriptCompletedResponse)(nil), // 35: coder.agent.v2.WorkspaceAgentScriptCompletedResponse - (*Timing)(nil), // 36: coder.agent.v2.Timing - (*WorkspaceApp_Healthcheck)(nil), // 37: coder.agent.v2.WorkspaceApp.Healthcheck - (*WorkspaceAgentMetadata_Result)(nil), // 38: coder.agent.v2.WorkspaceAgentMetadata.Result - (*WorkspaceAgentMetadata_Description)(nil), // 39: coder.agent.v2.WorkspaceAgentMetadata.Description - nil, // 40: coder.agent.v2.Manifest.EnvironmentVariablesEntry - nil, // 41: coder.agent.v2.Stats.ConnectionsByProtoEntry - (*Stats_Metric)(nil), // 42: coder.agent.v2.Stats.Metric - (*Stats_Metric_Label)(nil), // 43: coder.agent.v2.Stats.Metric.Label - (*BatchUpdateAppHealthRequest_HealthUpdate)(nil), // 44: coder.agent.v2.BatchUpdateAppHealthRequest.HealthUpdate - (*durationpb.Duration)(nil), // 45: google.protobuf.Duration - (*proto.DERPMap)(nil), // 46: coder.tailnet.v2.DERPMap - (*timestamppb.Timestamp)(nil), // 47: google.protobuf.Timestamp + (AppHealth)(0), // 0: coder.agent.v2.AppHealth + (WorkspaceApp_SharingLevel)(0), // 1: coder.agent.v2.WorkspaceApp.SharingLevel + (WorkspaceApp_Health)(0), // 2: coder.agent.v2.WorkspaceApp.Health + (Stats_Metric_Type)(0), // 3: coder.agent.v2.Stats.Metric.Type + (Lifecycle_State)(0), // 4: coder.agent.v2.Lifecycle.State + (Startup_Subsystem)(0), // 5: coder.agent.v2.Startup.Subsystem + (Log_Level)(0), // 6: coder.agent.v2.Log.Level + (Timing_Stage)(0), // 7: coder.agent.v2.Timing.Stage + (Timing_Status)(0), // 8: coder.agent.v2.Timing.Status + (*WorkspaceApp)(nil), // 9: coder.agent.v2.WorkspaceApp + (*WorkspaceAgentScript)(nil), // 10: coder.agent.v2.WorkspaceAgentScript + (*WorkspaceAgentMetadata)(nil), // 11: coder.agent.v2.WorkspaceAgentMetadata + (*Manifest)(nil), // 12: coder.agent.v2.Manifest + (*GetManifestRequest)(nil), // 13: coder.agent.v2.GetManifestRequest + (*ServiceBanner)(nil), // 14: coder.agent.v2.ServiceBanner + (*GetServiceBannerRequest)(nil), // 15: coder.agent.v2.GetServiceBannerRequest + (*Stats)(nil), // 16: coder.agent.v2.Stats + (*UpdateStatsRequest)(nil), // 17: coder.agent.v2.UpdateStatsRequest + (*UpdateStatsResponse)(nil), // 18: coder.agent.v2.UpdateStatsResponse + (*Lifecycle)(nil), // 19: coder.agent.v2.Lifecycle + (*UpdateLifecycleRequest)(nil), // 20: coder.agent.v2.UpdateLifecycleRequest + (*BatchUpdateAppHealthRequest)(nil), // 21: coder.agent.v2.BatchUpdateAppHealthRequest + (*BatchUpdateAppHealthResponse)(nil), // 22: coder.agent.v2.BatchUpdateAppHealthResponse + (*Startup)(nil), // 23: coder.agent.v2.Startup + (*UpdateStartupRequest)(nil), // 24: coder.agent.v2.UpdateStartupRequest + (*Metadata)(nil), // 25: coder.agent.v2.Metadata + (*BatchUpdateMetadataRequest)(nil), // 26: coder.agent.v2.BatchUpdateMetadataRequest + (*BatchUpdateMetadataResponse)(nil), // 27: coder.agent.v2.BatchUpdateMetadataResponse + (*Log)(nil), // 28: coder.agent.v2.Log + (*BatchCreateLogsRequest)(nil), // 29: coder.agent.v2.BatchCreateLogsRequest + (*BatchCreateLogsResponse)(nil), // 30: coder.agent.v2.BatchCreateLogsResponse + (*GetAnnouncementBannersRequest)(nil), // 31: coder.agent.v2.GetAnnouncementBannersRequest + (*GetAnnouncementBannersResponse)(nil), // 32: coder.agent.v2.GetAnnouncementBannersResponse + (*BannerConfig)(nil), // 33: coder.agent.v2.BannerConfig + (*WorkspaceAgentScriptCompletedRequest)(nil), // 34: coder.agent.v2.WorkspaceAgentScriptCompletedRequest + (*WorkspaceAgentScriptCompletedResponse)(nil), // 35: coder.agent.v2.WorkspaceAgentScriptCompletedResponse + (*Timing)(nil), // 36: coder.agent.v2.Timing + (*GetResourcesMonitoringConfigurationRequest)(nil), // 37: coder.agent.v2.GetResourcesMonitoringConfigurationRequest + (*GetResourcesMonitoringConfigurationResponse)(nil), // 38: coder.agent.v2.GetResourcesMonitoringConfigurationResponse + (*PushResourcesMonitoringUsageRequest)(nil), // 39: coder.agent.v2.PushResourcesMonitoringUsageRequest + (*PushResourcesMonitoringUsageResponse)(nil), // 40: coder.agent.v2.PushResourcesMonitoringUsageResponse + (*WorkspaceApp_Healthcheck)(nil), // 41: coder.agent.v2.WorkspaceApp.Healthcheck + (*WorkspaceAgentMetadata_Result)(nil), // 42: coder.agent.v2.WorkspaceAgentMetadata.Result + (*WorkspaceAgentMetadata_Description)(nil), // 43: coder.agent.v2.WorkspaceAgentMetadata.Description + nil, // 44: coder.agent.v2.Manifest.EnvironmentVariablesEntry + nil, // 45: coder.agent.v2.Stats.ConnectionsByProtoEntry + (*Stats_Metric)(nil), // 46: coder.agent.v2.Stats.Metric + (*Stats_Metric_Label)(nil), // 47: coder.agent.v2.Stats.Metric.Label + (*BatchUpdateAppHealthRequest_HealthUpdate)(nil), // 48: coder.agent.v2.BatchUpdateAppHealthRequest.HealthUpdate + (*GetResourcesMonitoringConfigurationResponse_Config)(nil), // 49: coder.agent.v2.GetResourcesMonitoringConfigurationResponse.Config + (*PushResourcesMonitoringUsageRequest_Datapoint)(nil), // 50: coder.agent.v2.PushResourcesMonitoringUsageRequest.Datapoint + (*PushResourcesMonitoringUsageRequest_Datapoint_VolumeUsage)(nil), // 51: coder.agent.v2.PushResourcesMonitoringUsageRequest.Datapoint.VolumeUsage + (*durationpb.Duration)(nil), // 52: google.protobuf.Duration + (*proto.DERPMap)(nil), // 53: coder.tailnet.v2.DERPMap + (*timestamppb.Timestamp)(nil), // 54: google.protobuf.Timestamp } var file_agent_proto_agent_proto_depIdxs = []int32{ 1, // 0: coder.agent.v2.WorkspaceApp.sharing_level:type_name -> coder.agent.v2.WorkspaceApp.SharingLevel - 37, // 1: coder.agent.v2.WorkspaceApp.healthcheck:type_name -> coder.agent.v2.WorkspaceApp.Healthcheck + 41, // 1: coder.agent.v2.WorkspaceApp.healthcheck:type_name -> coder.agent.v2.WorkspaceApp.Healthcheck 2, // 2: coder.agent.v2.WorkspaceApp.health:type_name -> coder.agent.v2.WorkspaceApp.Health - 45, // 3: coder.agent.v2.WorkspaceAgentScript.timeout:type_name -> google.protobuf.Duration - 38, // 4: coder.agent.v2.WorkspaceAgentMetadata.result:type_name -> coder.agent.v2.WorkspaceAgentMetadata.Result - 39, // 5: coder.agent.v2.WorkspaceAgentMetadata.description:type_name -> coder.agent.v2.WorkspaceAgentMetadata.Description - 40, // 6: coder.agent.v2.Manifest.environment_variables:type_name -> coder.agent.v2.Manifest.EnvironmentVariablesEntry - 46, // 7: coder.agent.v2.Manifest.derp_map:type_name -> coder.tailnet.v2.DERPMap + 52, // 3: coder.agent.v2.WorkspaceAgentScript.timeout:type_name -> google.protobuf.Duration + 42, // 4: coder.agent.v2.WorkspaceAgentMetadata.result:type_name -> coder.agent.v2.WorkspaceAgentMetadata.Result + 43, // 5: coder.agent.v2.WorkspaceAgentMetadata.description:type_name -> coder.agent.v2.WorkspaceAgentMetadata.Description + 44, // 6: coder.agent.v2.Manifest.environment_variables:type_name -> coder.agent.v2.Manifest.EnvironmentVariablesEntry + 53, // 7: coder.agent.v2.Manifest.derp_map:type_name -> coder.tailnet.v2.DERPMap 10, // 8: coder.agent.v2.Manifest.scripts:type_name -> coder.agent.v2.WorkspaceAgentScript 9, // 9: coder.agent.v2.Manifest.apps:type_name -> coder.agent.v2.WorkspaceApp - 39, // 10: coder.agent.v2.Manifest.metadata:type_name -> coder.agent.v2.WorkspaceAgentMetadata.Description - 41, // 11: coder.agent.v2.Stats.connections_by_proto:type_name -> coder.agent.v2.Stats.ConnectionsByProtoEntry - 42, // 12: coder.agent.v2.Stats.metrics:type_name -> coder.agent.v2.Stats.Metric + 43, // 10: coder.agent.v2.Manifest.metadata:type_name -> coder.agent.v2.WorkspaceAgentMetadata.Description + 45, // 11: coder.agent.v2.Stats.connections_by_proto:type_name -> coder.agent.v2.Stats.ConnectionsByProtoEntry + 46, // 12: coder.agent.v2.Stats.metrics:type_name -> coder.agent.v2.Stats.Metric 16, // 13: coder.agent.v2.UpdateStatsRequest.stats:type_name -> coder.agent.v2.Stats - 45, // 14: coder.agent.v2.UpdateStatsResponse.report_interval:type_name -> google.protobuf.Duration + 52, // 14: coder.agent.v2.UpdateStatsResponse.report_interval:type_name -> google.protobuf.Duration 4, // 15: coder.agent.v2.Lifecycle.state:type_name -> coder.agent.v2.Lifecycle.State - 47, // 16: coder.agent.v2.Lifecycle.changed_at:type_name -> google.protobuf.Timestamp + 54, // 16: coder.agent.v2.Lifecycle.changed_at:type_name -> google.protobuf.Timestamp 19, // 17: coder.agent.v2.UpdateLifecycleRequest.lifecycle:type_name -> coder.agent.v2.Lifecycle - 44, // 18: coder.agent.v2.BatchUpdateAppHealthRequest.updates:type_name -> coder.agent.v2.BatchUpdateAppHealthRequest.HealthUpdate + 48, // 18: coder.agent.v2.BatchUpdateAppHealthRequest.updates:type_name -> coder.agent.v2.BatchUpdateAppHealthRequest.HealthUpdate 5, // 19: coder.agent.v2.Startup.subsystems:type_name -> coder.agent.v2.Startup.Subsystem 23, // 20: coder.agent.v2.UpdateStartupRequest.startup:type_name -> coder.agent.v2.Startup - 38, // 21: coder.agent.v2.Metadata.result:type_name -> coder.agent.v2.WorkspaceAgentMetadata.Result + 42, // 21: coder.agent.v2.Metadata.result:type_name -> coder.agent.v2.WorkspaceAgentMetadata.Result 25, // 22: coder.agent.v2.BatchUpdateMetadataRequest.metadata:type_name -> coder.agent.v2.Metadata - 47, // 23: coder.agent.v2.Log.created_at:type_name -> google.protobuf.Timestamp + 54, // 23: coder.agent.v2.Log.created_at:type_name -> google.protobuf.Timestamp 6, // 24: coder.agent.v2.Log.level:type_name -> coder.agent.v2.Log.Level 28, // 25: coder.agent.v2.BatchCreateLogsRequest.logs:type_name -> coder.agent.v2.Log 33, // 26: coder.agent.v2.GetAnnouncementBannersResponse.announcement_banners:type_name -> coder.agent.v2.BannerConfig 36, // 27: coder.agent.v2.WorkspaceAgentScriptCompletedRequest.timing:type_name -> coder.agent.v2.Timing - 47, // 28: coder.agent.v2.Timing.start:type_name -> google.protobuf.Timestamp - 47, // 29: coder.agent.v2.Timing.end:type_name -> google.protobuf.Timestamp + 54, // 28: coder.agent.v2.Timing.start:type_name -> google.protobuf.Timestamp + 54, // 29: coder.agent.v2.Timing.end:type_name -> google.protobuf.Timestamp 7, // 30: coder.agent.v2.Timing.stage:type_name -> coder.agent.v2.Timing.Stage 8, // 31: coder.agent.v2.Timing.status:type_name -> coder.agent.v2.Timing.Status - 45, // 32: coder.agent.v2.WorkspaceApp.Healthcheck.interval:type_name -> google.protobuf.Duration - 47, // 33: coder.agent.v2.WorkspaceAgentMetadata.Result.collected_at:type_name -> google.protobuf.Timestamp - 45, // 34: coder.agent.v2.WorkspaceAgentMetadata.Description.interval:type_name -> google.protobuf.Duration - 45, // 35: coder.agent.v2.WorkspaceAgentMetadata.Description.timeout:type_name -> google.protobuf.Duration - 3, // 36: coder.agent.v2.Stats.Metric.type:type_name -> coder.agent.v2.Stats.Metric.Type - 43, // 37: coder.agent.v2.Stats.Metric.labels:type_name -> coder.agent.v2.Stats.Metric.Label - 0, // 38: coder.agent.v2.BatchUpdateAppHealthRequest.HealthUpdate.health:type_name -> coder.agent.v2.AppHealth - 13, // 39: coder.agent.v2.Agent.GetManifest:input_type -> coder.agent.v2.GetManifestRequest - 15, // 40: coder.agent.v2.Agent.GetServiceBanner:input_type -> coder.agent.v2.GetServiceBannerRequest - 17, // 41: coder.agent.v2.Agent.UpdateStats:input_type -> coder.agent.v2.UpdateStatsRequest - 20, // 42: coder.agent.v2.Agent.UpdateLifecycle:input_type -> coder.agent.v2.UpdateLifecycleRequest - 21, // 43: coder.agent.v2.Agent.BatchUpdateAppHealths:input_type -> coder.agent.v2.BatchUpdateAppHealthRequest - 24, // 44: coder.agent.v2.Agent.UpdateStartup:input_type -> coder.agent.v2.UpdateStartupRequest - 26, // 45: coder.agent.v2.Agent.BatchUpdateMetadata:input_type -> coder.agent.v2.BatchUpdateMetadataRequest - 29, // 46: coder.agent.v2.Agent.BatchCreateLogs:input_type -> coder.agent.v2.BatchCreateLogsRequest - 31, // 47: coder.agent.v2.Agent.GetAnnouncementBanners:input_type -> coder.agent.v2.GetAnnouncementBannersRequest - 34, // 48: coder.agent.v2.Agent.ScriptCompleted:input_type -> coder.agent.v2.WorkspaceAgentScriptCompletedRequest - 12, // 49: coder.agent.v2.Agent.GetManifest:output_type -> coder.agent.v2.Manifest - 14, // 50: coder.agent.v2.Agent.GetServiceBanner:output_type -> coder.agent.v2.ServiceBanner - 18, // 51: coder.agent.v2.Agent.UpdateStats:output_type -> coder.agent.v2.UpdateStatsResponse - 19, // 52: coder.agent.v2.Agent.UpdateLifecycle:output_type -> coder.agent.v2.Lifecycle - 22, // 53: coder.agent.v2.Agent.BatchUpdateAppHealths:output_type -> coder.agent.v2.BatchUpdateAppHealthResponse - 23, // 54: coder.agent.v2.Agent.UpdateStartup:output_type -> coder.agent.v2.Startup - 27, // 55: coder.agent.v2.Agent.BatchUpdateMetadata:output_type -> coder.agent.v2.BatchUpdateMetadataResponse - 30, // 56: coder.agent.v2.Agent.BatchCreateLogs:output_type -> coder.agent.v2.BatchCreateLogsResponse - 32, // 57: coder.agent.v2.Agent.GetAnnouncementBanners:output_type -> coder.agent.v2.GetAnnouncementBannersResponse - 35, // 58: coder.agent.v2.Agent.ScriptCompleted:output_type -> coder.agent.v2.WorkspaceAgentScriptCompletedResponse - 49, // [49:59] is the sub-list for method output_type - 39, // [39:49] is the sub-list for method input_type - 39, // [39:39] is the sub-list for extension type_name - 39, // [39:39] is the sub-list for extension extendee - 0, // [0:39] is the sub-list for field type_name + 49, // 32: coder.agent.v2.GetResourcesMonitoringConfigurationResponse.config:type_name -> coder.agent.v2.GetResourcesMonitoringConfigurationResponse.Config + 50, // 33: coder.agent.v2.PushResourcesMonitoringUsageRequest.datapoints:type_name -> coder.agent.v2.PushResourcesMonitoringUsageRequest.Datapoint + 52, // 34: coder.agent.v2.WorkspaceApp.Healthcheck.interval:type_name -> google.protobuf.Duration + 54, // 35: coder.agent.v2.WorkspaceAgentMetadata.Result.collected_at:type_name -> google.protobuf.Timestamp + 52, // 36: coder.agent.v2.WorkspaceAgentMetadata.Description.interval:type_name -> google.protobuf.Duration + 52, // 37: coder.agent.v2.WorkspaceAgentMetadata.Description.timeout:type_name -> google.protobuf.Duration + 3, // 38: coder.agent.v2.Stats.Metric.type:type_name -> coder.agent.v2.Stats.Metric.Type + 47, // 39: coder.agent.v2.Stats.Metric.labels:type_name -> coder.agent.v2.Stats.Metric.Label + 0, // 40: coder.agent.v2.BatchUpdateAppHealthRequest.HealthUpdate.health:type_name -> coder.agent.v2.AppHealth + 54, // 41: coder.agent.v2.PushResourcesMonitoringUsageRequest.Datapoint.collected_at:type_name -> google.protobuf.Timestamp + 51, // 42: coder.agent.v2.PushResourcesMonitoringUsageRequest.Datapoint.volumes:type_name -> coder.agent.v2.PushResourcesMonitoringUsageRequest.Datapoint.VolumeUsage + 13, // 43: coder.agent.v2.Agent.GetManifest:input_type -> coder.agent.v2.GetManifestRequest + 15, // 44: coder.agent.v2.Agent.GetServiceBanner:input_type -> coder.agent.v2.GetServiceBannerRequest + 17, // 45: coder.agent.v2.Agent.UpdateStats:input_type -> coder.agent.v2.UpdateStatsRequest + 20, // 46: coder.agent.v2.Agent.UpdateLifecycle:input_type -> coder.agent.v2.UpdateLifecycleRequest + 21, // 47: coder.agent.v2.Agent.BatchUpdateAppHealths:input_type -> coder.agent.v2.BatchUpdateAppHealthRequest + 24, // 48: coder.agent.v2.Agent.UpdateStartup:input_type -> coder.agent.v2.UpdateStartupRequest + 26, // 49: coder.agent.v2.Agent.BatchUpdateMetadata:input_type -> coder.agent.v2.BatchUpdateMetadataRequest + 29, // 50: coder.agent.v2.Agent.BatchCreateLogs:input_type -> coder.agent.v2.BatchCreateLogsRequest + 31, // 51: coder.agent.v2.Agent.GetAnnouncementBanners:input_type -> coder.agent.v2.GetAnnouncementBannersRequest + 34, // 52: coder.agent.v2.Agent.ScriptCompleted:input_type -> coder.agent.v2.WorkspaceAgentScriptCompletedRequest + 37, // 53: coder.agent.v2.Agent.GetResourcesMonitoringConfiguration:input_type -> coder.agent.v2.GetResourcesMonitoringConfigurationRequest + 39, // 54: coder.agent.v2.Agent.PushResourcesMonitoringUsage:input_type -> coder.agent.v2.PushResourcesMonitoringUsageRequest + 12, // 55: coder.agent.v2.Agent.GetManifest:output_type -> coder.agent.v2.Manifest + 14, // 56: coder.agent.v2.Agent.GetServiceBanner:output_type -> coder.agent.v2.ServiceBanner + 18, // 57: coder.agent.v2.Agent.UpdateStats:output_type -> coder.agent.v2.UpdateStatsResponse + 19, // 58: coder.agent.v2.Agent.UpdateLifecycle:output_type -> coder.agent.v2.Lifecycle + 22, // 59: coder.agent.v2.Agent.BatchUpdateAppHealths:output_type -> coder.agent.v2.BatchUpdateAppHealthResponse + 23, // 60: coder.agent.v2.Agent.UpdateStartup:output_type -> coder.agent.v2.Startup + 27, // 61: coder.agent.v2.Agent.BatchUpdateMetadata:output_type -> coder.agent.v2.BatchUpdateMetadataResponse + 30, // 62: coder.agent.v2.Agent.BatchCreateLogs:output_type -> coder.agent.v2.BatchCreateLogsResponse + 32, // 63: coder.agent.v2.Agent.GetAnnouncementBanners:output_type -> coder.agent.v2.GetAnnouncementBannersResponse + 35, // 64: coder.agent.v2.Agent.ScriptCompleted:output_type -> coder.agent.v2.WorkspaceAgentScriptCompletedResponse + 38, // 65: coder.agent.v2.Agent.GetResourcesMonitoringConfiguration:output_type -> coder.agent.v2.GetResourcesMonitoringConfigurationResponse + 40, // 66: coder.agent.v2.Agent.PushResourcesMonitoringUsage:output_type -> coder.agent.v2.PushResourcesMonitoringUsageResponse + 55, // [55:67] is the sub-list for method output_type + 43, // [43:55] is the sub-list for method input_type + 43, // [43:43] is the sub-list for extension type_name + 43, // [43:43] is the sub-list for extension extendee + 0, // [0:43] is the sub-list for field type_name } func init() { file_agent_proto_agent_proto_init() } @@ -3641,7 +4104,7 @@ func file_agent_proto_agent_proto_init() { } } file_agent_proto_agent_proto_msgTypes[28].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*WorkspaceApp_Healthcheck); i { + switch v := v.(*GetResourcesMonitoringConfigurationRequest); i { case 0: return &v.state case 1: @@ -3653,7 +4116,7 @@ func file_agent_proto_agent_proto_init() { } } file_agent_proto_agent_proto_msgTypes[29].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*WorkspaceAgentMetadata_Result); i { + switch v := v.(*GetResourcesMonitoringConfigurationResponse); i { case 0: return &v.state case 1: @@ -3665,7 +4128,31 @@ func file_agent_proto_agent_proto_init() { } } file_agent_proto_agent_proto_msgTypes[30].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*WorkspaceAgentMetadata_Description); i { + switch v := v.(*PushResourcesMonitoringUsageRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_agent_proto_agent_proto_msgTypes[31].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PushResourcesMonitoringUsageResponse); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_agent_proto_agent_proto_msgTypes[32].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*WorkspaceApp_Healthcheck); i { case 0: return &v.state case 1: @@ -3677,7 +4164,7 @@ func file_agent_proto_agent_proto_init() { } } file_agent_proto_agent_proto_msgTypes[33].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Stats_Metric); i { + switch v := v.(*WorkspaceAgentMetadata_Result); i { case 0: return &v.state case 1: @@ -3689,6 +4176,30 @@ func file_agent_proto_agent_proto_init() { } } file_agent_proto_agent_proto_msgTypes[34].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*WorkspaceAgentMetadata_Description); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_agent_proto_agent_proto_msgTypes[37].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Stats_Metric); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_agent_proto_agent_proto_msgTypes[38].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Stats_Metric_Label); i { case 0: return &v.state @@ -3700,7 +4211,7 @@ func file_agent_proto_agent_proto_init() { return nil } } - file_agent_proto_agent_proto_msgTypes[35].Exporter = func(v interface{}, i int) interface{} { + file_agent_proto_agent_proto_msgTypes[39].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*BatchUpdateAppHealthRequest_HealthUpdate); i { case 0: return &v.state @@ -3712,6 +4223,42 @@ func file_agent_proto_agent_proto_init() { return nil } } + file_agent_proto_agent_proto_msgTypes[40].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*GetResourcesMonitoringConfigurationResponse_Config); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_agent_proto_agent_proto_msgTypes[41].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PushResourcesMonitoringUsageRequest_Datapoint); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_agent_proto_agent_proto_msgTypes[42].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PushResourcesMonitoringUsageRequest_Datapoint_VolumeUsage); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } } type x struct{} out := protoimpl.TypeBuilder{ @@ -3719,7 +4266,7 @@ func file_agent_proto_agent_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_agent_proto_agent_proto_rawDesc, NumEnums: 9, - NumMessages: 36, + NumMessages: 43, NumExtensions: 0, NumServices: 1, }, diff --git a/agent/proto/agent.proto b/agent/proto/agent.proto index f307066fcbfdf..3b887141248f7 100644 --- a/agent/proto/agent.proto +++ b/agent/proto/agent.proto @@ -295,6 +295,39 @@ message Timing { Status status = 6; } +message GetResourcesMonitoringConfigurationRequest { +} + +message GetResourcesMonitoringConfigurationResponse { + bool enabled = 1; + message Config { + int32 num_datapoints = 1; + int32 tick_interval = 2; // expressed in seconds + } + Config config = 2; + repeated string monitored_volumes = 3; +} + +message PushResourcesMonitoringUsageRequest { + message Datapoint { + message VolumeUsage { + string volume = 1; + int32 space_used = 2; + int32 space_total = 3; + } + + google.protobuf.Timestamp collected_at = 1; + int32 memory_used = 2; + int32 memory_total =3; + repeated VolumeUsage volumes = 4; + + } + repeated Datapoint datapoints = 1; +} + +message PushResourcesMonitoringUsageResponse { +} + service Agent { rpc GetManifest(GetManifestRequest) returns (Manifest); rpc GetServiceBanner(GetServiceBannerRequest) returns (ServiceBanner); @@ -306,4 +339,6 @@ service Agent { rpc BatchCreateLogs(BatchCreateLogsRequest) returns (BatchCreateLogsResponse); rpc GetAnnouncementBanners(GetAnnouncementBannersRequest) returns (GetAnnouncementBannersResponse); rpc ScriptCompleted(WorkspaceAgentScriptCompletedRequest) returns (WorkspaceAgentScriptCompletedResponse); + rpc GetResourcesMonitoringConfiguration(GetResourcesMonitoringConfigurationRequest) returns (GetResourcesMonitoringConfigurationResponse); + rpc PushResourcesMonitoringUsage(PushResourcesMonitoringUsageRequest) returns (PushResourcesMonitoringUsageResponse); } diff --git a/agent/proto/agent_drpc.pb.go b/agent/proto/agent_drpc.pb.go index 9f7e21c96248c..2a90380185732 100644 --- a/agent/proto/agent_drpc.pb.go +++ b/agent/proto/agent_drpc.pb.go @@ -48,6 +48,8 @@ type DRPCAgentClient interface { BatchCreateLogs(ctx context.Context, in *BatchCreateLogsRequest) (*BatchCreateLogsResponse, error) GetAnnouncementBanners(ctx context.Context, in *GetAnnouncementBannersRequest) (*GetAnnouncementBannersResponse, error) ScriptCompleted(ctx context.Context, in *WorkspaceAgentScriptCompletedRequest) (*WorkspaceAgentScriptCompletedResponse, error) + GetResourcesMonitoringConfiguration(ctx context.Context, in *GetResourcesMonitoringConfigurationRequest) (*GetResourcesMonitoringConfigurationResponse, error) + PushResourcesMonitoringUsage(ctx context.Context, in *PushResourcesMonitoringUsageRequest) (*PushResourcesMonitoringUsageResponse, error) } type drpcAgentClient struct { @@ -150,6 +152,24 @@ func (c *drpcAgentClient) ScriptCompleted(ctx context.Context, in *WorkspaceAgen return out, nil } +func (c *drpcAgentClient) GetResourcesMonitoringConfiguration(ctx context.Context, in *GetResourcesMonitoringConfigurationRequest) (*GetResourcesMonitoringConfigurationResponse, error) { + out := new(GetResourcesMonitoringConfigurationResponse) + err := c.cc.Invoke(ctx, "/coder.agent.v2.Agent/GetResourcesMonitoringConfiguration", drpcEncoding_File_agent_proto_agent_proto{}, in, out) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *drpcAgentClient) PushResourcesMonitoringUsage(ctx context.Context, in *PushResourcesMonitoringUsageRequest) (*PushResourcesMonitoringUsageResponse, error) { + out := new(PushResourcesMonitoringUsageResponse) + err := c.cc.Invoke(ctx, "/coder.agent.v2.Agent/PushResourcesMonitoringUsage", drpcEncoding_File_agent_proto_agent_proto{}, in, out) + if err != nil { + return nil, err + } + return out, nil +} + type DRPCAgentServer interface { GetManifest(context.Context, *GetManifestRequest) (*Manifest, error) GetServiceBanner(context.Context, *GetServiceBannerRequest) (*ServiceBanner, error) @@ -161,6 +181,8 @@ type DRPCAgentServer interface { BatchCreateLogs(context.Context, *BatchCreateLogsRequest) (*BatchCreateLogsResponse, error) GetAnnouncementBanners(context.Context, *GetAnnouncementBannersRequest) (*GetAnnouncementBannersResponse, error) ScriptCompleted(context.Context, *WorkspaceAgentScriptCompletedRequest) (*WorkspaceAgentScriptCompletedResponse, error) + GetResourcesMonitoringConfiguration(context.Context, *GetResourcesMonitoringConfigurationRequest) (*GetResourcesMonitoringConfigurationResponse, error) + PushResourcesMonitoringUsage(context.Context, *PushResourcesMonitoringUsageRequest) (*PushResourcesMonitoringUsageResponse, error) } type DRPCAgentUnimplementedServer struct{} @@ -205,9 +227,17 @@ func (s *DRPCAgentUnimplementedServer) ScriptCompleted(context.Context, *Workspa return nil, drpcerr.WithCode(errors.New("Unimplemented"), drpcerr.Unimplemented) } +func (s *DRPCAgentUnimplementedServer) GetResourcesMonitoringConfiguration(context.Context, *GetResourcesMonitoringConfigurationRequest) (*GetResourcesMonitoringConfigurationResponse, error) { + return nil, drpcerr.WithCode(errors.New("Unimplemented"), drpcerr.Unimplemented) +} + +func (s *DRPCAgentUnimplementedServer) PushResourcesMonitoringUsage(context.Context, *PushResourcesMonitoringUsageRequest) (*PushResourcesMonitoringUsageResponse, error) { + return nil, drpcerr.WithCode(errors.New("Unimplemented"), drpcerr.Unimplemented) +} + type DRPCAgentDescription struct{} -func (DRPCAgentDescription) NumMethods() int { return 10 } +func (DRPCAgentDescription) NumMethods() int { return 12 } func (DRPCAgentDescription) Method(n int) (string, drpc.Encoding, drpc.Receiver, interface{}, bool) { switch n { @@ -301,6 +331,24 @@ func (DRPCAgentDescription) Method(n int) (string, drpc.Encoding, drpc.Receiver, in1.(*WorkspaceAgentScriptCompletedRequest), ) }, DRPCAgentServer.ScriptCompleted, true + case 10: + return "/coder.agent.v2.Agent/GetResourcesMonitoringConfiguration", drpcEncoding_File_agent_proto_agent_proto{}, + func(srv interface{}, ctx context.Context, in1, in2 interface{}) (drpc.Message, error) { + return srv.(DRPCAgentServer). + GetResourcesMonitoringConfiguration( + ctx, + in1.(*GetResourcesMonitoringConfigurationRequest), + ) + }, DRPCAgentServer.GetResourcesMonitoringConfiguration, true + case 11: + return "/coder.agent.v2.Agent/PushResourcesMonitoringUsage", drpcEncoding_File_agent_proto_agent_proto{}, + func(srv interface{}, ctx context.Context, in1, in2 interface{}) (drpc.Message, error) { + return srv.(DRPCAgentServer). + PushResourcesMonitoringUsage( + ctx, + in1.(*PushResourcesMonitoringUsageRequest), + ) + }, DRPCAgentServer.PushResourcesMonitoringUsage, true default: return "", nil, nil, nil, false } @@ -469,3 +517,35 @@ func (x *drpcAgent_ScriptCompletedStream) SendAndClose(m *WorkspaceAgentScriptCo } return x.CloseSend() } + +type DRPCAgent_GetResourcesMonitoringConfigurationStream interface { + drpc.Stream + SendAndClose(*GetResourcesMonitoringConfigurationResponse) error +} + +type drpcAgent_GetResourcesMonitoringConfigurationStream struct { + drpc.Stream +} + +func (x *drpcAgent_GetResourcesMonitoringConfigurationStream) SendAndClose(m *GetResourcesMonitoringConfigurationResponse) error { + if err := x.MsgSend(m, drpcEncoding_File_agent_proto_agent_proto{}); err != nil { + return err + } + return x.CloseSend() +} + +type DRPCAgent_PushResourcesMonitoringUsageStream interface { + drpc.Stream + SendAndClose(*PushResourcesMonitoringUsageResponse) error +} + +type drpcAgent_PushResourcesMonitoringUsageStream struct { + drpc.Stream +} + +func (x *drpcAgent_PushResourcesMonitoringUsageStream) SendAndClose(m *PushResourcesMonitoringUsageResponse) error { + if err := x.MsgSend(m, drpcEncoding_File_agent_proto_agent_proto{}); err != nil { + return err + } + return x.CloseSend() +} diff --git a/agent/proto/agent_drpc_old.go b/agent/proto/agent_drpc_old.go index f46afaba42596..3d2ea1c574f82 100644 --- a/agent/proto/agent_drpc_old.go +++ b/agent/proto/agent_drpc_old.go @@ -40,3 +40,7 @@ type DRPCAgentClient23 interface { DRPCAgentClient22 ScriptCompleted(ctx context.Context, in *WorkspaceAgentScriptCompletedRequest) (*WorkspaceAgentScriptCompletedResponse, error) } + +type DRPCAgentClient24 interface { + DRPCAgentClient23 +} diff --git a/coderd/agentapi/api.go b/coderd/agentapi/api.go index 62fe6fad8d4de..cffeca049ef56 100644 --- a/coderd/agentapi/api.go +++ b/coderd/agentapi/api.go @@ -42,6 +42,7 @@ type API struct { *LifecycleAPI *AppsAPI *MetadataAPI + *ResourcesMonitoringAPI *LogsAPI *ScriptsAPI *tailnet.DRPCService @@ -102,6 +103,8 @@ func New(opts Options) *API { appearanceFetcher: opts.AppearanceFetcher, } + api.ResourcesMonitoringAPI = &ResourcesMonitoringAPI{} + api.StatsAPI = &StatsAPI{ AgentFn: api.agent, Database: opts.Database, diff --git a/coderd/agentapi/resources_monitoring.go b/coderd/agentapi/resources_monitoring.go new file mode 100644 index 0000000000000..9dd7534328c23 --- /dev/null +++ b/coderd/agentapi/resources_monitoring.go @@ -0,0 +1,20 @@ +package agentapi + +import ( + "context" + + "golang.org/x/xerrors" + + "github.com/coder/coder/v2/agent/proto" +) + +type ResourcesMonitoringAPI struct { +} + +func (a *ResourcesMonitoringAPI) GetResourcesMonitoringConfiguration(ctx context.Context, _ *proto.GetResourcesMonitoringConfigurationRequest) (*proto.GetResourcesMonitoringConfigurationResponse, error) { + return nil, xerrors.Errorf("GetResourcesMonitoringConfiguration is not implemented") +} + +func (a *ResourcesMonitoringAPI) PushResourcesMonitoringUsage(ctx context.Context, _ *proto.PushResourcesMonitoringUsageRequest) (*proto.PushResourcesMonitoringUsageResponse, error) { + return nil, xerrors.Errorf("PushResourcesMonitoringUsage is not implemented") +} diff --git a/codersdk/agentsdk/agentsdk.go b/codersdk/agentsdk/agentsdk.go index 9e6362eb7dd54..64a9b8fc2ab9d 100644 --- a/codersdk/agentsdk/agentsdk.go +++ b/codersdk/agentsdk/agentsdk.go @@ -229,6 +229,18 @@ func (c *Client) ConnectRPC23(ctx context.Context) ( return proto.NewDRPCAgentClient(conn), tailnetproto.NewDRPCTailnetClient(conn), nil } +// ConnectRPC24 returns a dRPC client to the Agent API v2.4. It is useful when you want to be +// maximally compatible with Coderd Release Versions from 2.xx+ // TODO @vincent: define version +func (c *Client) ConnectRPC24(ctx context.Context) ( + proto.DRPCAgentClient24, tailnetproto.DRPCTailnetClient24, error, +) { + conn, err := c.connectRPCVersion(ctx, apiversion.New(2, 4)) + if err != nil { + return nil, nil, err + } + return proto.NewDRPCAgentClient(conn), tailnetproto.NewDRPCTailnetClient(conn), nil +} + // ConnectRPC connects to the workspace agent API and tailnet API func (c *Client) ConnectRPC(ctx context.Context) (drpc.Conn, error) { return c.connectRPCVersion(ctx, proto.CurrentVersion) diff --git a/tailnet/proto/tailnet_drpc_old.go b/tailnet/proto/tailnet_drpc_old.go index 64be85d87542f..dfe902bdd5416 100644 --- a/tailnet/proto/tailnet_drpc_old.go +++ b/tailnet/proto/tailnet_drpc_old.go @@ -34,3 +34,9 @@ type DRPCTailnetClient23 interface { RefreshResumeToken(ctx context.Context, in *RefreshResumeTokenRequest) (*RefreshResumeTokenResponse, error) WorkspaceUpdates(ctx context.Context, in *WorkspaceUpdatesRequest) (DRPCTailnet_WorkspaceUpdatesClient, error) } + +// DRPCTailnetClient24 is the Tailnet API at v2.4. It is functionally identical to 2.3, because the +// change was to the Agent API (ResourcesMonitoring methods). +type DRPCTailnetClient24 interface { + DRPCTailnetClient23 +} diff --git a/tailnet/proto/version.go b/tailnet/proto/version.go index 8d8bd5343d2ee..20121471f026e 100644 --- a/tailnet/proto/version.go +++ b/tailnet/proto/version.go @@ -38,9 +38,13 @@ import ( // shipped in Coder v2.16.0, but we forgot to increment the API version. If // you dial for API v2.2, you MAY be connected to a server that supports // ScriptCompleted, but be prepared to process "unsupported" errors.) +// +// API v2.4: +// - Shipped in Coder v2.19.0 +// - Added support for ResourcesMonitoring RPCs on the Agent API. const ( CurrentMajor = 2 - CurrentMinor = 3 + CurrentMinor = 4 ) var CurrentVersion = apiversion.New(CurrentMajor, CurrentMinor) From 7b2d19e95d02d2f9a12a5c6e45e34e9015a0404d Mon Sep 17 00:00:00 2001 From: defelmnq Date: Mon, 10 Feb 2025 04:01:09 +0000 Subject: [PATCH 02/32] improve function for resources monitoring --- agent/agent.go | 2 + agent/proto/agent.pb.go | 429 ++++++++++++++---------- agent/proto/agent.proto | 13 +- agent/proto/agent_drpc_old.go | 2 + coderd/agentapi/api.go | 6 +- coderd/agentapi/resources_monitoring.go | 45 ++- coderd/database/dbauthz/dbauthz.go | 24 +- coderd/database/modelmethods.go | 8 + coderd/workspaceagents_test.go | 2 +- 9 files changed, 325 insertions(+), 206 deletions(-) diff --git a/agent/agent.go b/agent/agent.go index a049ff83be0c4..0e60f1d030e53 100644 --- a/agent/agent.go +++ b/agent/agent.go @@ -785,6 +785,8 @@ func (a *agent) run() (retErr error) { // metadata reporting can cease as soon as we start gracefully shutting down connMan.startAgentAPI("report metadata", gracefulShutdownBehaviorStop, a.reportMetadata) + connMan.startAgentAPI("resources monitor", gracefulShutdownBehaviorStop, a.pushResourcesMonitoring) + // channels to sync goroutines below // handle manifest // | diff --git a/agent/proto/agent.pb.go b/agent/proto/agent.pb.go index 69dbcc5597590..109c7db90aa86 100644 --- a/agent/proto/agent.pb.go +++ b/agent/proto/agent.pb.go @@ -2945,9 +2945,8 @@ type PushResourcesMonitoringUsageRequest_Datapoint struct { unknownFields protoimpl.UnknownFields CollectedAt *timestamppb.Timestamp `protobuf:"bytes,1,opt,name=collected_at,json=collectedAt,proto3" json:"collected_at,omitempty"` - MemoryUsed int32 `protobuf:"varint,2,opt,name=memory_used,json=memoryUsed,proto3" json:"memory_used,omitempty"` - MemoryTotal int32 `protobuf:"varint,3,opt,name=memory_total,json=memoryTotal,proto3" json:"memory_total,omitempty"` - Volumes []*PushResourcesMonitoringUsageRequest_Datapoint_VolumeUsage `protobuf:"bytes,4,rep,name=volumes,proto3" json:"volumes,omitempty"` + Memory *PushResourcesMonitoringUsageRequest_Datapoint_MemoryUsage `protobuf:"bytes,2,opt,name=memory,proto3" json:"memory,omitempty"` + Volumes []*PushResourcesMonitoringUsageRequest_Datapoint_VolumeUsage `protobuf:"bytes,3,rep,name=volumes,proto3" json:"volumes,omitempty"` } func (x *PushResourcesMonitoringUsageRequest_Datapoint) Reset() { @@ -2989,25 +2988,73 @@ func (x *PushResourcesMonitoringUsageRequest_Datapoint) GetCollectedAt() *timest return nil } -func (x *PushResourcesMonitoringUsageRequest_Datapoint) GetMemoryUsed() int32 { +func (x *PushResourcesMonitoringUsageRequest_Datapoint) GetMemory() *PushResourcesMonitoringUsageRequest_Datapoint_MemoryUsage { if x != nil { - return x.MemoryUsed + return x.Memory } - return 0 + return nil } -func (x *PushResourcesMonitoringUsageRequest_Datapoint) GetMemoryTotal() int32 { +func (x *PushResourcesMonitoringUsageRequest_Datapoint) GetVolumes() []*PushResourcesMonitoringUsageRequest_Datapoint_VolumeUsage { if x != nil { - return x.MemoryTotal + return x.Volumes + } + return nil +} + +type PushResourcesMonitoringUsageRequest_Datapoint_MemoryUsage struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Used int64 `protobuf:"varint,1,opt,name=used,proto3" json:"used,omitempty"` + Total int64 `protobuf:"varint,2,opt,name=total,proto3" json:"total,omitempty"` +} + +func (x *PushResourcesMonitoringUsageRequest_Datapoint_MemoryUsage) Reset() { + *x = PushResourcesMonitoringUsageRequest_Datapoint_MemoryUsage{} + if protoimpl.UnsafeEnabled { + mi := &file_agent_proto_agent_proto_msgTypes[42] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PushResourcesMonitoringUsageRequest_Datapoint_MemoryUsage) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PushResourcesMonitoringUsageRequest_Datapoint_MemoryUsage) ProtoMessage() {} + +func (x *PushResourcesMonitoringUsageRequest_Datapoint_MemoryUsage) ProtoReflect() protoreflect.Message { + mi := &file_agent_proto_agent_proto_msgTypes[42] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PushResourcesMonitoringUsageRequest_Datapoint_MemoryUsage.ProtoReflect.Descriptor instead. +func (*PushResourcesMonitoringUsageRequest_Datapoint_MemoryUsage) Descriptor() ([]byte, []int) { + return file_agent_proto_agent_proto_rawDescGZIP(), []int{30, 0, 0} +} + +func (x *PushResourcesMonitoringUsageRequest_Datapoint_MemoryUsage) GetUsed() int64 { + if x != nil { + return x.Used } return 0 } -func (x *PushResourcesMonitoringUsageRequest_Datapoint) GetVolumes() []*PushResourcesMonitoringUsageRequest_Datapoint_VolumeUsage { +func (x *PushResourcesMonitoringUsageRequest_Datapoint_MemoryUsage) GetTotal() int64 { if x != nil { - return x.Volumes + return x.Total } - return nil + return 0 } type PushResourcesMonitoringUsageRequest_Datapoint_VolumeUsage struct { @@ -3015,15 +3062,15 @@ type PushResourcesMonitoringUsageRequest_Datapoint_VolumeUsage struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Volume string `protobuf:"bytes,1,opt,name=volume,proto3" json:"volume,omitempty"` - SpaceUsed int32 `protobuf:"varint,2,opt,name=space_used,json=spaceUsed,proto3" json:"space_used,omitempty"` - SpaceTotal int32 `protobuf:"varint,3,opt,name=space_total,json=spaceTotal,proto3" json:"space_total,omitempty"` + Volume string `protobuf:"bytes,1,opt,name=volume,proto3" json:"volume,omitempty"` + Used int64 `protobuf:"varint,2,opt,name=used,proto3" json:"used,omitempty"` + Total int64 `protobuf:"varint,3,opt,name=total,proto3" json:"total,omitempty"` } func (x *PushResourcesMonitoringUsageRequest_Datapoint_VolumeUsage) Reset() { *x = PushResourcesMonitoringUsageRequest_Datapoint_VolumeUsage{} if protoimpl.UnsafeEnabled { - mi := &file_agent_proto_agent_proto_msgTypes[42] + mi := &file_agent_proto_agent_proto_msgTypes[43] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3036,7 +3083,7 @@ func (x *PushResourcesMonitoringUsageRequest_Datapoint_VolumeUsage) String() str func (*PushResourcesMonitoringUsageRequest_Datapoint_VolumeUsage) ProtoMessage() {} func (x *PushResourcesMonitoringUsageRequest_Datapoint_VolumeUsage) ProtoReflect() protoreflect.Message { - mi := &file_agent_proto_agent_proto_msgTypes[42] + mi := &file_agent_proto_agent_proto_msgTypes[43] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3049,7 +3096,7 @@ func (x *PushResourcesMonitoringUsageRequest_Datapoint_VolumeUsage) ProtoReflect // Deprecated: Use PushResourcesMonitoringUsageRequest_Datapoint_VolumeUsage.ProtoReflect.Descriptor instead. func (*PushResourcesMonitoringUsageRequest_Datapoint_VolumeUsage) Descriptor() ([]byte, []int) { - return file_agent_proto_agent_proto_rawDescGZIP(), []int{30, 0, 0} + return file_agent_proto_agent_proto_rawDescGZIP(), []int{30, 0, 1} } func (x *PushResourcesMonitoringUsageRequest_Datapoint_VolumeUsage) GetVolume() string { @@ -3059,16 +3106,16 @@ func (x *PushResourcesMonitoringUsageRequest_Datapoint_VolumeUsage) GetVolume() return "" } -func (x *PushResourcesMonitoringUsageRequest_Datapoint_VolumeUsage) GetSpaceUsed() int32 { +func (x *PushResourcesMonitoringUsageRequest_Datapoint_VolumeUsage) GetUsed() int64 { if x != nil { - return x.SpaceUsed + return x.Used } return 0 } -func (x *PushResourcesMonitoringUsageRequest_Datapoint_VolumeUsage) GetSpaceTotal() int32 { +func (x *PushResourcesMonitoringUsageRequest_Datapoint_VolumeUsage) GetTotal() int64 { if x != nil { - return x.SpaceTotal + return x.Total } return 0 } @@ -3488,7 +3535,7 @@ var file_agent_proto_agent_proto_rawDesc = []byte{ 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x6e, 0x75, 0x6d, 0x44, 0x61, 0x74, 0x61, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x74, 0x69, 0x63, 0x6b, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x74, 0x69, - 0x63, 0x6b, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x22, 0xe1, 0x03, 0x0a, 0x23, 0x50, + 0x63, 0x6b, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x22, 0xa3, 0x04, 0x0a, 0x23, 0x50, 0x75, 0x73, 0x68, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x5d, 0x0a, 0x0a, 0x64, 0x61, 0x74, 0x61, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, @@ -3497,122 +3544,126 @@ var file_agent_proto_agent_proto_rawDesc = []byte{ 0x75, 0x72, 0x63, 0x65, 0x73, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x0a, 0x64, 0x61, 0x74, 0x61, 0x70, 0x6f, 0x69, 0x6e, 0x74, - 0x73, 0x1a, 0xda, 0x02, 0x0a, 0x09, 0x44, 0x61, 0x74, 0x61, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, + 0x73, 0x1a, 0x9c, 0x03, 0x0a, 0x09, 0x44, 0x61, 0x74, 0x61, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x3d, 0x0a, 0x0c, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, - 0x70, 0x52, 0x0b, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x1f, - 0x0a, 0x0b, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x5f, 0x75, 0x73, 0x65, 0x64, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x05, 0x52, 0x0a, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x55, 0x73, 0x65, 0x64, 0x12, - 0x21, 0x0a, 0x0c, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x5f, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x54, 0x6f, 0x74, - 0x61, 0x6c, 0x12, 0x63, 0x0a, 0x07, 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x73, 0x18, 0x04, 0x20, - 0x03, 0x28, 0x0b, 0x32, 0x49, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, - 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x50, 0x75, 0x73, 0x68, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x73, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x55, 0x73, 0x61, 0x67, - 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x70, 0x6f, 0x69, - 0x6e, 0x74, 0x2e, 0x56, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x07, - 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x73, 0x1a, 0x65, 0x0a, 0x0b, 0x56, 0x6f, 0x6c, 0x75, 0x6d, - 0x65, 0x55, 0x73, 0x61, 0x67, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x12, 0x1d, - 0x0a, 0x0a, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x75, 0x73, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x05, 0x52, 0x09, 0x73, 0x70, 0x61, 0x63, 0x65, 0x55, 0x73, 0x65, 0x64, 0x12, 0x1f, 0x0a, - 0x0b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x5f, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x05, 0x52, 0x0a, 0x73, 0x70, 0x61, 0x63, 0x65, 0x54, 0x6f, 0x74, 0x61, 0x6c, 0x22, 0x26, - 0x0a, 0x24, 0x50, 0x75, 0x73, 0x68, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x4d, - 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2a, 0x63, 0x0a, 0x09, 0x41, 0x70, 0x70, 0x48, 0x65, 0x61, - 0x6c, 0x74, 0x68, 0x12, 0x1a, 0x0a, 0x16, 0x41, 0x50, 0x50, 0x5f, 0x48, 0x45, 0x41, 0x4c, 0x54, - 0x48, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, - 0x0c, 0x0a, 0x08, 0x44, 0x49, 0x53, 0x41, 0x42, 0x4c, 0x45, 0x44, 0x10, 0x01, 0x12, 0x10, 0x0a, - 0x0c, 0x49, 0x4e, 0x49, 0x54, 0x49, 0x41, 0x4c, 0x49, 0x5a, 0x49, 0x4e, 0x47, 0x10, 0x02, 0x12, - 0x0b, 0x0a, 0x07, 0x48, 0x45, 0x41, 0x4c, 0x54, 0x48, 0x59, 0x10, 0x03, 0x12, 0x0d, 0x0a, 0x09, - 0x55, 0x4e, 0x48, 0x45, 0x41, 0x4c, 0x54, 0x48, 0x59, 0x10, 0x04, 0x32, 0x9c, 0x0a, 0x0a, 0x05, - 0x41, 0x67, 0x65, 0x6e, 0x74, 0x12, 0x4b, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x4d, 0x61, 0x6e, 0x69, - 0x66, 0x65, 0x73, 0x74, 0x12, 0x22, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, - 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, - 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, - 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x4d, 0x61, 0x6e, 0x69, 0x66, 0x65, - 0x73, 0x74, 0x12, 0x5a, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, - 0x42, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x12, 0x27, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, - 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x42, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x1d, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, - 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x42, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x12, 0x56, - 0x0a, 0x0b, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x22, 0x2e, - 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x55, - 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x23, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, - 0x76, 0x32, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x0f, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, - 0x4c, 0x69, 0x66, 0x65, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x12, 0x26, 0x2e, 0x63, 0x6f, 0x64, 0x65, - 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, - 0x65, 0x4c, 0x69, 0x66, 0x65, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x19, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, - 0x76, 0x32, 0x2e, 0x4c, 0x69, 0x66, 0x65, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x12, 0x72, 0x0a, 0x15, - 0x42, 0x61, 0x74, 0x63, 0x68, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x70, 0x70, 0x48, 0x65, - 0x61, 0x6c, 0x74, 0x68, 0x73, 0x12, 0x2b, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, - 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x55, 0x70, 0x64, 0x61, - 0x74, 0x65, 0x41, 0x70, 0x70, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, - 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, - 0x70, 0x70, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x4e, 0x0a, 0x0d, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x74, 0x61, 0x72, 0x74, 0x75, - 0x70, 0x12, 0x24, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, - 0x76, 0x32, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, - 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, - 0x12, 0x6e, 0x0a, 0x13, 0x42, 0x61, 0x74, 0x63, 0x68, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, - 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x2a, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, - 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x55, 0x70, - 0x64, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, - 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, - 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x62, 0x0a, 0x0f, 0x42, 0x61, 0x74, 0x63, 0x68, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4c, - 0x6f, 0x67, 0x73, 0x12, 0x26, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, - 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, - 0x4c, 0x6f, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x63, 0x6f, - 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x61, 0x74, - 0x63, 0x68, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4c, 0x6f, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70, - 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x77, 0x0a, 0x16, 0x47, 0x65, 0x74, 0x41, 0x6e, 0x6e, 0x6f, 0x75, - 0x6e, 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x42, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x73, 0x12, 0x2d, + 0x70, 0x52, 0x0b, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x61, + 0x0a, 0x06, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x49, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, - 0x47, 0x65, 0x74, 0x41, 0x6e, 0x6e, 0x6f, 0x75, 0x6e, 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x42, - 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, - 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x47, - 0x65, 0x74, 0x41, 0x6e, 0x6e, 0x6f, 0x75, 0x6e, 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x42, 0x61, - 0x6e, 0x6e, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x7e, 0x0a, - 0x0f, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x64, - 0x12, 0x34, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, - 0x32, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x41, 0x67, 0x65, 0x6e, 0x74, - 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, - 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, - 0x65, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x43, 0x6f, 0x6d, 0x70, - 0x6c, 0x65, 0x74, 0x65, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x9e, 0x01, - 0x0a, 0x23, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x4d, 0x6f, - 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x3a, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, - 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x73, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x3b, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, - 0x76, 0x32, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x4d, - 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, - 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x89, - 0x01, 0x0a, 0x1c, 0x50, 0x75, 0x73, 0x68, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, - 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x55, 0x73, 0x61, 0x67, 0x65, 0x12, - 0x33, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, - 0x2e, 0x50, 0x75, 0x73, 0x68, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x4d, 0x6f, - 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, - 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x50, 0x75, 0x73, 0x68, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x73, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x55, 0x73, 0x61, - 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x27, 0x5a, 0x25, 0x67, 0x69, - 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2f, 0x63, - 0x6f, 0x64, 0x65, 0x72, 0x2f, 0x76, 0x32, 0x2f, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2f, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x50, 0x75, 0x73, 0x68, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x4d, 0x6f, 0x6e, + 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x2e, 0x4d, 0x65, + 0x6d, 0x6f, 0x72, 0x79, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x06, 0x6d, 0x65, 0x6d, 0x6f, 0x72, + 0x79, 0x12, 0x63, 0x0a, 0x07, 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x49, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, + 0x2e, 0x76, 0x32, 0x2e, 0x50, 0x75, 0x73, 0x68, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x73, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x55, 0x73, 0x61, 0x67, 0x65, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x70, 0x6f, 0x69, 0x6e, + 0x74, 0x2e, 0x56, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x07, 0x76, + 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x73, 0x1a, 0x37, 0x0a, 0x0b, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, + 0x55, 0x73, 0x61, 0x67, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x04, 0x75, 0x73, 0x65, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x74, + 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x1a, + 0x4f, 0x0a, 0x0b, 0x56, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x55, 0x73, 0x61, 0x67, 0x65, 0x12, 0x16, + 0x0a, 0x06, 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, + 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x64, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x75, 0x73, 0x65, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, + 0x74, 0x61, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, + 0x22, 0x26, 0x0a, 0x24, 0x50, 0x75, 0x73, 0x68, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x73, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x55, 0x73, 0x61, 0x67, 0x65, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2a, 0x63, 0x0a, 0x09, 0x41, 0x70, 0x70, 0x48, + 0x65, 0x61, 0x6c, 0x74, 0x68, 0x12, 0x1a, 0x0a, 0x16, 0x41, 0x50, 0x50, 0x5f, 0x48, 0x45, 0x41, + 0x4c, 0x54, 0x48, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, + 0x00, 0x12, 0x0c, 0x0a, 0x08, 0x44, 0x49, 0x53, 0x41, 0x42, 0x4c, 0x45, 0x44, 0x10, 0x01, 0x12, + 0x10, 0x0a, 0x0c, 0x49, 0x4e, 0x49, 0x54, 0x49, 0x41, 0x4c, 0x49, 0x5a, 0x49, 0x4e, 0x47, 0x10, + 0x02, 0x12, 0x0b, 0x0a, 0x07, 0x48, 0x45, 0x41, 0x4c, 0x54, 0x48, 0x59, 0x10, 0x03, 0x12, 0x0d, + 0x0a, 0x09, 0x55, 0x4e, 0x48, 0x45, 0x41, 0x4c, 0x54, 0x48, 0x59, 0x10, 0x04, 0x32, 0x9c, 0x0a, + 0x0a, 0x05, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x12, 0x4b, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x4d, 0x61, + 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x12, 0x22, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, + 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x61, 0x6e, 0x69, 0x66, + 0x65, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x63, 0x6f, 0x64, + 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x4d, 0x61, 0x6e, 0x69, + 0x66, 0x65, 0x73, 0x74, 0x12, 0x5a, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, + 0x63, 0x65, 0x42, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x12, 0x27, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, + 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x42, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x1d, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, + 0x76, 0x32, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x42, 0x61, 0x6e, 0x6e, 0x65, 0x72, + 0x12, 0x56, 0x0a, 0x0b, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, + 0x22, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, + 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, + 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x0f, 0x55, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x4c, 0x69, 0x66, 0x65, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x12, 0x26, 0x2e, 0x63, 0x6f, + 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x55, 0x70, 0x64, + 0x61, 0x74, 0x65, 0x4c, 0x69, 0x66, 0x65, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, + 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x4c, 0x69, 0x66, 0x65, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x12, 0x72, + 0x0a, 0x15, 0x42, 0x61, 0x74, 0x63, 0x68, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x70, 0x70, + 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x73, 0x12, 0x2b, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, + 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x55, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x41, 0x70, 0x70, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, + 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x55, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x41, 0x70, 0x70, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x4e, 0x0a, 0x0d, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x74, 0x61, 0x72, + 0x74, 0x75, 0x70, 0x12, 0x24, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, + 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x74, 0x61, 0x72, 0x74, + 0x75, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x63, 0x6f, 0x64, 0x65, + 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, + 0x75, 0x70, 0x12, 0x6e, 0x0a, 0x13, 0x42, 0x61, 0x74, 0x63, 0x68, 0x55, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x2a, 0x2e, 0x63, 0x6f, 0x64, 0x65, + 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, + 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, + 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x55, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x62, 0x0a, 0x0f, 0x42, 0x61, 0x74, 0x63, 0x68, 0x43, 0x72, 0x65, 0x61, 0x74, + 0x65, 0x4c, 0x6f, 0x67, 0x73, 0x12, 0x26, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, + 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x43, 0x72, 0x65, 0x61, + 0x74, 0x65, 0x4c, 0x6f, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, + 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x42, + 0x61, 0x74, 0x63, 0x68, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4c, 0x6f, 0x67, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x77, 0x0a, 0x16, 0x47, 0x65, 0x74, 0x41, 0x6e, 0x6e, + 0x6f, 0x75, 0x6e, 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x42, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x73, + 0x12, 0x2d, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, + 0x32, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x6e, 0x6e, 0x6f, 0x75, 0x6e, 0x63, 0x65, 0x6d, 0x65, 0x6e, + 0x74, 0x42, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x2e, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, + 0x2e, 0x47, 0x65, 0x74, 0x41, 0x6e, 0x6e, 0x6f, 0x75, 0x6e, 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, + 0x42, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x7e, 0x0a, 0x0f, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, + 0x65, 0x64, 0x12, 0x34, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, + 0x2e, 0x76, 0x32, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x41, 0x67, 0x65, + 0x6e, 0x74, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, + 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, + 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, + 0x61, 0x63, 0x65, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x43, 0x6f, + 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, + 0x9e, 0x01, 0x0a, 0x23, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, + 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, + 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x3a, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, + 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x73, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x43, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x3b, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, + 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x73, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x89, 0x01, 0x0a, 0x1c, 0x50, 0x75, 0x73, 0x68, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x73, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x55, 0x73, 0x61, 0x67, + 0x65, 0x12, 0x33, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, + 0x76, 0x32, 0x2e, 0x50, 0x75, 0x73, 0x68, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, + 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, + 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x50, 0x75, 0x73, 0x68, 0x52, 0x65, 0x73, 0x6f, + 0x75, 0x72, 0x63, 0x65, 0x73, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x55, + 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x27, 0x5a, 0x25, + 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x6f, 0x64, 0x65, 0x72, + 0x2f, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2f, 0x76, 0x32, 0x2f, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2f, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -3628,7 +3679,7 @@ func file_agent_proto_agent_proto_rawDescGZIP() []byte { } var file_agent_proto_agent_proto_enumTypes = make([]protoimpl.EnumInfo, 9) -var file_agent_proto_agent_proto_msgTypes = make([]protoimpl.MessageInfo, 43) +var file_agent_proto_agent_proto_msgTypes = make([]protoimpl.MessageInfo, 44) var file_agent_proto_agent_proto_goTypes = []interface{}{ (AppHealth)(0), // 0: coder.agent.v2.AppHealth (WorkspaceApp_SharingLevel)(0), // 1: coder.agent.v2.WorkspaceApp.SharingLevel @@ -3681,84 +3732,86 @@ var file_agent_proto_agent_proto_goTypes = []interface{}{ (*BatchUpdateAppHealthRequest_HealthUpdate)(nil), // 48: coder.agent.v2.BatchUpdateAppHealthRequest.HealthUpdate (*GetResourcesMonitoringConfigurationResponse_Config)(nil), // 49: coder.agent.v2.GetResourcesMonitoringConfigurationResponse.Config (*PushResourcesMonitoringUsageRequest_Datapoint)(nil), // 50: coder.agent.v2.PushResourcesMonitoringUsageRequest.Datapoint - (*PushResourcesMonitoringUsageRequest_Datapoint_VolumeUsage)(nil), // 51: coder.agent.v2.PushResourcesMonitoringUsageRequest.Datapoint.VolumeUsage - (*durationpb.Duration)(nil), // 52: google.protobuf.Duration - (*proto.DERPMap)(nil), // 53: coder.tailnet.v2.DERPMap - (*timestamppb.Timestamp)(nil), // 54: google.protobuf.Timestamp + (*PushResourcesMonitoringUsageRequest_Datapoint_MemoryUsage)(nil), // 51: coder.agent.v2.PushResourcesMonitoringUsageRequest.Datapoint.MemoryUsage + (*PushResourcesMonitoringUsageRequest_Datapoint_VolumeUsage)(nil), // 52: coder.agent.v2.PushResourcesMonitoringUsageRequest.Datapoint.VolumeUsage + (*durationpb.Duration)(nil), // 53: google.protobuf.Duration + (*proto.DERPMap)(nil), // 54: coder.tailnet.v2.DERPMap + (*timestamppb.Timestamp)(nil), // 55: google.protobuf.Timestamp } var file_agent_proto_agent_proto_depIdxs = []int32{ 1, // 0: coder.agent.v2.WorkspaceApp.sharing_level:type_name -> coder.agent.v2.WorkspaceApp.SharingLevel 41, // 1: coder.agent.v2.WorkspaceApp.healthcheck:type_name -> coder.agent.v2.WorkspaceApp.Healthcheck 2, // 2: coder.agent.v2.WorkspaceApp.health:type_name -> coder.agent.v2.WorkspaceApp.Health - 52, // 3: coder.agent.v2.WorkspaceAgentScript.timeout:type_name -> google.protobuf.Duration + 53, // 3: coder.agent.v2.WorkspaceAgentScript.timeout:type_name -> google.protobuf.Duration 42, // 4: coder.agent.v2.WorkspaceAgentMetadata.result:type_name -> coder.agent.v2.WorkspaceAgentMetadata.Result 43, // 5: coder.agent.v2.WorkspaceAgentMetadata.description:type_name -> coder.agent.v2.WorkspaceAgentMetadata.Description 44, // 6: coder.agent.v2.Manifest.environment_variables:type_name -> coder.agent.v2.Manifest.EnvironmentVariablesEntry - 53, // 7: coder.agent.v2.Manifest.derp_map:type_name -> coder.tailnet.v2.DERPMap + 54, // 7: coder.agent.v2.Manifest.derp_map:type_name -> coder.tailnet.v2.DERPMap 10, // 8: coder.agent.v2.Manifest.scripts:type_name -> coder.agent.v2.WorkspaceAgentScript 9, // 9: coder.agent.v2.Manifest.apps:type_name -> coder.agent.v2.WorkspaceApp 43, // 10: coder.agent.v2.Manifest.metadata:type_name -> coder.agent.v2.WorkspaceAgentMetadata.Description 45, // 11: coder.agent.v2.Stats.connections_by_proto:type_name -> coder.agent.v2.Stats.ConnectionsByProtoEntry 46, // 12: coder.agent.v2.Stats.metrics:type_name -> coder.agent.v2.Stats.Metric 16, // 13: coder.agent.v2.UpdateStatsRequest.stats:type_name -> coder.agent.v2.Stats - 52, // 14: coder.agent.v2.UpdateStatsResponse.report_interval:type_name -> google.protobuf.Duration + 53, // 14: coder.agent.v2.UpdateStatsResponse.report_interval:type_name -> google.protobuf.Duration 4, // 15: coder.agent.v2.Lifecycle.state:type_name -> coder.agent.v2.Lifecycle.State - 54, // 16: coder.agent.v2.Lifecycle.changed_at:type_name -> google.protobuf.Timestamp + 55, // 16: coder.agent.v2.Lifecycle.changed_at:type_name -> google.protobuf.Timestamp 19, // 17: coder.agent.v2.UpdateLifecycleRequest.lifecycle:type_name -> coder.agent.v2.Lifecycle 48, // 18: coder.agent.v2.BatchUpdateAppHealthRequest.updates:type_name -> coder.agent.v2.BatchUpdateAppHealthRequest.HealthUpdate 5, // 19: coder.agent.v2.Startup.subsystems:type_name -> coder.agent.v2.Startup.Subsystem 23, // 20: coder.agent.v2.UpdateStartupRequest.startup:type_name -> coder.agent.v2.Startup 42, // 21: coder.agent.v2.Metadata.result:type_name -> coder.agent.v2.WorkspaceAgentMetadata.Result 25, // 22: coder.agent.v2.BatchUpdateMetadataRequest.metadata:type_name -> coder.agent.v2.Metadata - 54, // 23: coder.agent.v2.Log.created_at:type_name -> google.protobuf.Timestamp + 55, // 23: coder.agent.v2.Log.created_at:type_name -> google.protobuf.Timestamp 6, // 24: coder.agent.v2.Log.level:type_name -> coder.agent.v2.Log.Level 28, // 25: coder.agent.v2.BatchCreateLogsRequest.logs:type_name -> coder.agent.v2.Log 33, // 26: coder.agent.v2.GetAnnouncementBannersResponse.announcement_banners:type_name -> coder.agent.v2.BannerConfig 36, // 27: coder.agent.v2.WorkspaceAgentScriptCompletedRequest.timing:type_name -> coder.agent.v2.Timing - 54, // 28: coder.agent.v2.Timing.start:type_name -> google.protobuf.Timestamp - 54, // 29: coder.agent.v2.Timing.end:type_name -> google.protobuf.Timestamp + 55, // 28: coder.agent.v2.Timing.start:type_name -> google.protobuf.Timestamp + 55, // 29: coder.agent.v2.Timing.end:type_name -> google.protobuf.Timestamp 7, // 30: coder.agent.v2.Timing.stage:type_name -> coder.agent.v2.Timing.Stage 8, // 31: coder.agent.v2.Timing.status:type_name -> coder.agent.v2.Timing.Status 49, // 32: coder.agent.v2.GetResourcesMonitoringConfigurationResponse.config:type_name -> coder.agent.v2.GetResourcesMonitoringConfigurationResponse.Config 50, // 33: coder.agent.v2.PushResourcesMonitoringUsageRequest.datapoints:type_name -> coder.agent.v2.PushResourcesMonitoringUsageRequest.Datapoint - 52, // 34: coder.agent.v2.WorkspaceApp.Healthcheck.interval:type_name -> google.protobuf.Duration - 54, // 35: coder.agent.v2.WorkspaceAgentMetadata.Result.collected_at:type_name -> google.protobuf.Timestamp - 52, // 36: coder.agent.v2.WorkspaceAgentMetadata.Description.interval:type_name -> google.protobuf.Duration - 52, // 37: coder.agent.v2.WorkspaceAgentMetadata.Description.timeout:type_name -> google.protobuf.Duration + 53, // 34: coder.agent.v2.WorkspaceApp.Healthcheck.interval:type_name -> google.protobuf.Duration + 55, // 35: coder.agent.v2.WorkspaceAgentMetadata.Result.collected_at:type_name -> google.protobuf.Timestamp + 53, // 36: coder.agent.v2.WorkspaceAgentMetadata.Description.interval:type_name -> google.protobuf.Duration + 53, // 37: coder.agent.v2.WorkspaceAgentMetadata.Description.timeout:type_name -> google.protobuf.Duration 3, // 38: coder.agent.v2.Stats.Metric.type:type_name -> coder.agent.v2.Stats.Metric.Type 47, // 39: coder.agent.v2.Stats.Metric.labels:type_name -> coder.agent.v2.Stats.Metric.Label 0, // 40: coder.agent.v2.BatchUpdateAppHealthRequest.HealthUpdate.health:type_name -> coder.agent.v2.AppHealth - 54, // 41: coder.agent.v2.PushResourcesMonitoringUsageRequest.Datapoint.collected_at:type_name -> google.protobuf.Timestamp - 51, // 42: coder.agent.v2.PushResourcesMonitoringUsageRequest.Datapoint.volumes:type_name -> coder.agent.v2.PushResourcesMonitoringUsageRequest.Datapoint.VolumeUsage - 13, // 43: coder.agent.v2.Agent.GetManifest:input_type -> coder.agent.v2.GetManifestRequest - 15, // 44: coder.agent.v2.Agent.GetServiceBanner:input_type -> coder.agent.v2.GetServiceBannerRequest - 17, // 45: coder.agent.v2.Agent.UpdateStats:input_type -> coder.agent.v2.UpdateStatsRequest - 20, // 46: coder.agent.v2.Agent.UpdateLifecycle:input_type -> coder.agent.v2.UpdateLifecycleRequest - 21, // 47: coder.agent.v2.Agent.BatchUpdateAppHealths:input_type -> coder.agent.v2.BatchUpdateAppHealthRequest - 24, // 48: coder.agent.v2.Agent.UpdateStartup:input_type -> coder.agent.v2.UpdateStartupRequest - 26, // 49: coder.agent.v2.Agent.BatchUpdateMetadata:input_type -> coder.agent.v2.BatchUpdateMetadataRequest - 29, // 50: coder.agent.v2.Agent.BatchCreateLogs:input_type -> coder.agent.v2.BatchCreateLogsRequest - 31, // 51: coder.agent.v2.Agent.GetAnnouncementBanners:input_type -> coder.agent.v2.GetAnnouncementBannersRequest - 34, // 52: coder.agent.v2.Agent.ScriptCompleted:input_type -> coder.agent.v2.WorkspaceAgentScriptCompletedRequest - 37, // 53: coder.agent.v2.Agent.GetResourcesMonitoringConfiguration:input_type -> coder.agent.v2.GetResourcesMonitoringConfigurationRequest - 39, // 54: coder.agent.v2.Agent.PushResourcesMonitoringUsage:input_type -> coder.agent.v2.PushResourcesMonitoringUsageRequest - 12, // 55: coder.agent.v2.Agent.GetManifest:output_type -> coder.agent.v2.Manifest - 14, // 56: coder.agent.v2.Agent.GetServiceBanner:output_type -> coder.agent.v2.ServiceBanner - 18, // 57: coder.agent.v2.Agent.UpdateStats:output_type -> coder.agent.v2.UpdateStatsResponse - 19, // 58: coder.agent.v2.Agent.UpdateLifecycle:output_type -> coder.agent.v2.Lifecycle - 22, // 59: coder.agent.v2.Agent.BatchUpdateAppHealths:output_type -> coder.agent.v2.BatchUpdateAppHealthResponse - 23, // 60: coder.agent.v2.Agent.UpdateStartup:output_type -> coder.agent.v2.Startup - 27, // 61: coder.agent.v2.Agent.BatchUpdateMetadata:output_type -> coder.agent.v2.BatchUpdateMetadataResponse - 30, // 62: coder.agent.v2.Agent.BatchCreateLogs:output_type -> coder.agent.v2.BatchCreateLogsResponse - 32, // 63: coder.agent.v2.Agent.GetAnnouncementBanners:output_type -> coder.agent.v2.GetAnnouncementBannersResponse - 35, // 64: coder.agent.v2.Agent.ScriptCompleted:output_type -> coder.agent.v2.WorkspaceAgentScriptCompletedResponse - 38, // 65: coder.agent.v2.Agent.GetResourcesMonitoringConfiguration:output_type -> coder.agent.v2.GetResourcesMonitoringConfigurationResponse - 40, // 66: coder.agent.v2.Agent.PushResourcesMonitoringUsage:output_type -> coder.agent.v2.PushResourcesMonitoringUsageResponse - 55, // [55:67] is the sub-list for method output_type - 43, // [43:55] is the sub-list for method input_type - 43, // [43:43] is the sub-list for extension type_name - 43, // [43:43] is the sub-list for extension extendee - 0, // [0:43] is the sub-list for field type_name + 55, // 41: coder.agent.v2.PushResourcesMonitoringUsageRequest.Datapoint.collected_at:type_name -> google.protobuf.Timestamp + 51, // 42: coder.agent.v2.PushResourcesMonitoringUsageRequest.Datapoint.memory:type_name -> coder.agent.v2.PushResourcesMonitoringUsageRequest.Datapoint.MemoryUsage + 52, // 43: coder.agent.v2.PushResourcesMonitoringUsageRequest.Datapoint.volumes:type_name -> coder.agent.v2.PushResourcesMonitoringUsageRequest.Datapoint.VolumeUsage + 13, // 44: coder.agent.v2.Agent.GetManifest:input_type -> coder.agent.v2.GetManifestRequest + 15, // 45: coder.agent.v2.Agent.GetServiceBanner:input_type -> coder.agent.v2.GetServiceBannerRequest + 17, // 46: coder.agent.v2.Agent.UpdateStats:input_type -> coder.agent.v2.UpdateStatsRequest + 20, // 47: coder.agent.v2.Agent.UpdateLifecycle:input_type -> coder.agent.v2.UpdateLifecycleRequest + 21, // 48: coder.agent.v2.Agent.BatchUpdateAppHealths:input_type -> coder.agent.v2.BatchUpdateAppHealthRequest + 24, // 49: coder.agent.v2.Agent.UpdateStartup:input_type -> coder.agent.v2.UpdateStartupRequest + 26, // 50: coder.agent.v2.Agent.BatchUpdateMetadata:input_type -> coder.agent.v2.BatchUpdateMetadataRequest + 29, // 51: coder.agent.v2.Agent.BatchCreateLogs:input_type -> coder.agent.v2.BatchCreateLogsRequest + 31, // 52: coder.agent.v2.Agent.GetAnnouncementBanners:input_type -> coder.agent.v2.GetAnnouncementBannersRequest + 34, // 53: coder.agent.v2.Agent.ScriptCompleted:input_type -> coder.agent.v2.WorkspaceAgentScriptCompletedRequest + 37, // 54: coder.agent.v2.Agent.GetResourcesMonitoringConfiguration:input_type -> coder.agent.v2.GetResourcesMonitoringConfigurationRequest + 39, // 55: coder.agent.v2.Agent.PushResourcesMonitoringUsage:input_type -> coder.agent.v2.PushResourcesMonitoringUsageRequest + 12, // 56: coder.agent.v2.Agent.GetManifest:output_type -> coder.agent.v2.Manifest + 14, // 57: coder.agent.v2.Agent.GetServiceBanner:output_type -> coder.agent.v2.ServiceBanner + 18, // 58: coder.agent.v2.Agent.UpdateStats:output_type -> coder.agent.v2.UpdateStatsResponse + 19, // 59: coder.agent.v2.Agent.UpdateLifecycle:output_type -> coder.agent.v2.Lifecycle + 22, // 60: coder.agent.v2.Agent.BatchUpdateAppHealths:output_type -> coder.agent.v2.BatchUpdateAppHealthResponse + 23, // 61: coder.agent.v2.Agent.UpdateStartup:output_type -> coder.agent.v2.Startup + 27, // 62: coder.agent.v2.Agent.BatchUpdateMetadata:output_type -> coder.agent.v2.BatchUpdateMetadataResponse + 30, // 63: coder.agent.v2.Agent.BatchCreateLogs:output_type -> coder.agent.v2.BatchCreateLogsResponse + 32, // 64: coder.agent.v2.Agent.GetAnnouncementBanners:output_type -> coder.agent.v2.GetAnnouncementBannersResponse + 35, // 65: coder.agent.v2.Agent.ScriptCompleted:output_type -> coder.agent.v2.WorkspaceAgentScriptCompletedResponse + 38, // 66: coder.agent.v2.Agent.GetResourcesMonitoringConfiguration:output_type -> coder.agent.v2.GetResourcesMonitoringConfigurationResponse + 40, // 67: coder.agent.v2.Agent.PushResourcesMonitoringUsage:output_type -> coder.agent.v2.PushResourcesMonitoringUsageResponse + 56, // [56:68] is the sub-list for method output_type + 44, // [44:56] is the sub-list for method input_type + 44, // [44:44] is the sub-list for extension type_name + 44, // [44:44] is the sub-list for extension extendee + 0, // [0:44] is the sub-list for field type_name } func init() { file_agent_proto_agent_proto_init() } @@ -4248,6 +4301,18 @@ func file_agent_proto_agent_proto_init() { } } file_agent_proto_agent_proto_msgTypes[42].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PushResourcesMonitoringUsageRequest_Datapoint_MemoryUsage); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_agent_proto_agent_proto_msgTypes[43].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*PushResourcesMonitoringUsageRequest_Datapoint_VolumeUsage); i { case 0: return &v.state @@ -4266,7 +4331,7 @@ func file_agent_proto_agent_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_agent_proto_agent_proto_rawDesc, NumEnums: 9, - NumMessages: 43, + NumMessages: 44, NumExtensions: 0, NumServices: 1, }, diff --git a/agent/proto/agent.proto b/agent/proto/agent.proto index 3b887141248f7..b2a9d010bf026 100644 --- a/agent/proto/agent.proto +++ b/agent/proto/agent.proto @@ -310,16 +310,19 @@ message GetResourcesMonitoringConfigurationResponse { message PushResourcesMonitoringUsageRequest { message Datapoint { + message MemoryUsage { + int64 used = 1; + int64 total = 2; + } message VolumeUsage { string volume = 1; - int32 space_used = 2; - int32 space_total = 3; + int64 used = 2; + int64 total = 3; } google.protobuf.Timestamp collected_at = 1; - int32 memory_used = 2; - int32 memory_total =3; - repeated VolumeUsage volumes = 4; + MemoryUsage memory = 2; + repeated VolumeUsage volumes = 3; } repeated Datapoint datapoints = 1; diff --git a/agent/proto/agent_drpc_old.go b/agent/proto/agent_drpc_old.go index 3d2ea1c574f82..bf1668b8f7483 100644 --- a/agent/proto/agent_drpc_old.go +++ b/agent/proto/agent_drpc_old.go @@ -43,4 +43,6 @@ type DRPCAgentClient23 interface { type DRPCAgentClient24 interface { DRPCAgentClient23 + GetResourcesMonitoringConfiguration(ctx context.Context, in *GetResourcesMonitoringConfigurationRequest) (*GetResourcesMonitoringConfigurationResponse, error) + PushResourcesMonitoringUsage(ctx context.Context, in *PushResourcesMonitoringUsageRequest) (*PushResourcesMonitoringUsageResponse, error) } diff --git a/coderd/agentapi/api.go b/coderd/agentapi/api.go index cffeca049ef56..ed54bef6fbf46 100644 --- a/coderd/agentapi/api.go +++ b/coderd/agentapi/api.go @@ -103,7 +103,11 @@ func New(opts Options) *API { appearanceFetcher: opts.AppearanceFetcher, } - api.ResourcesMonitoringAPI = &ResourcesMonitoringAPI{} + api.ResourcesMonitoringAPI = &ResourcesMonitoringAPI{ + Log: opts.Log, + AgentFn: api.agent, + Database: opts.Database, + } api.StatsAPI = &StatsAPI{ AgentFn: api.agent, diff --git a/coderd/agentapi/resources_monitoring.go b/coderd/agentapi/resources_monitoring.go index 9dd7534328c23..1d44836738f75 100644 --- a/coderd/agentapi/resources_monitoring.go +++ b/coderd/agentapi/resources_monitoring.go @@ -2,19 +2,54 @@ package agentapi import ( "context" + "database/sql" + "errors" - "golang.org/x/xerrors" - + "cdr.dev/slog" "github.com/coder/coder/v2/agent/proto" + "github.com/coder/coder/v2/coderd/database" ) type ResourcesMonitoringAPI struct { + AgentFn func(context.Context) (database.WorkspaceAgent, error) + Database database.Store + Log slog.Logger } func (a *ResourcesMonitoringAPI) GetResourcesMonitoringConfiguration(ctx context.Context, _ *proto.GetResourcesMonitoringConfigurationRequest) (*proto.GetResourcesMonitoringConfigurationResponse, error) { - return nil, xerrors.Errorf("GetResourcesMonitoringConfiguration is not implemented") + agent, err := a.AgentFn(ctx) + if err != nil { + return nil, err + } + + _, err = a.Database.FetchMemoryResourceMonitorsByAgentID(ctx, agent.ID) + if err != nil && !errors.Is(err, sql.ErrNoRows) { + return nil, err + } + + volumeMonitors, err := a.Database.FetchVolumesResourceMonitorsByAgentID(ctx, agent.ID) + if err != nil { + return nil, err + } + + volumes := make([]string, 0, len(volumeMonitors)) + for _, monitor := range volumeMonitors { + volumes = append(volumes, monitor.Path) + } + + return &proto.GetResourcesMonitoringConfigurationResponse{ + Enabled: false, + Config: &proto.GetResourcesMonitoringConfigurationResponse_Config{ + TickInterval: 10, + NumDatapoints: 20, + }, + MonitoredVolumes: volumes, + }, nil } -func (a *ResourcesMonitoringAPI) PushResourcesMonitoringUsage(ctx context.Context, _ *proto.PushResourcesMonitoringUsageRequest) (*proto.PushResourcesMonitoringUsageResponse, error) { - return nil, xerrors.Errorf("PushResourcesMonitoringUsage is not implemented") +func (a *ResourcesMonitoringAPI) PushResourcesMonitoringUsage(ctx context.Context, req *proto.PushResourcesMonitoringUsageRequest) (*proto.PushResourcesMonitoringUsageResponse, error) { + a.Log.Info(ctx, "resources monitoring usage received", + slog.F("request", req)) + + return &proto.PushResourcesMonitoringUsageResponse{}, nil } diff --git a/coderd/database/dbauthz/dbauthz.go b/coderd/database/dbauthz/dbauthz.go index a85b13925c298..7d5f020010ea2 100644 --- a/coderd/database/dbauthz/dbauthz.go +++ b/coderd/database/dbauthz/dbauthz.go @@ -1392,9 +1392,9 @@ func (q *querier) FavoriteWorkspace(ctx context.Context, id uuid.UUID) error { } func (q *querier) FetchMemoryResourceMonitorsByAgentID(ctx context.Context, agentID uuid.UUID) (database.WorkspaceAgentMemoryResourceMonitor, error) { - if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceWorkspaceAgentResourceMonitor); err != nil { - return database.WorkspaceAgentMemoryResourceMonitor{}, err - } + // if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceWorkspaceAgentResourceMonitor); err != nil { + // return database.WorkspaceAgentMemoryResourceMonitor{}, err + // } return q.db.FetchMemoryResourceMonitorsByAgentID(ctx, agentID) } @@ -1407,9 +1407,9 @@ func (q *querier) FetchNewMessageMetadata(ctx context.Context, arg database.Fetc } func (q *querier) FetchVolumesResourceMonitorsByAgentID(ctx context.Context, agentID uuid.UUID) ([]database.WorkspaceAgentVolumeResourceMonitor, error) { - if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceWorkspaceAgentResourceMonitor); err != nil { - return nil, err - } + // if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceWorkspaceAgentResourceMonitor); err != nil { + // return nil, err + // } return q.db.FetchVolumesResourceMonitorsByAgentID(ctx, agentID) } @@ -3020,9 +3020,9 @@ func (q *querier) InsertLicense(ctx context.Context, arg database.InsertLicenseP } func (q *querier) InsertMemoryResourceMonitor(ctx context.Context, arg database.InsertMemoryResourceMonitorParams) (database.WorkspaceAgentMemoryResourceMonitor, error) { - if err := q.authorizeContext(ctx, policy.ActionCreate, rbac.ResourceWorkspaceAgentResourceMonitor); err != nil { - return database.WorkspaceAgentMemoryResourceMonitor{}, err - } + // if err := q.authorizeContext(ctx, policy.ActionCreate, rbac.ResourceWorkspaceAgentResourceMonitor); err != nil { + // return database.WorkspaceAgentMemoryResourceMonitor{}, err + // } return q.db.InsertMemoryResourceMonitor(ctx, arg) } @@ -3220,9 +3220,9 @@ func (q *querier) InsertUserLink(ctx context.Context, arg database.InsertUserLin } func (q *querier) InsertVolumeResourceMonitor(ctx context.Context, arg database.InsertVolumeResourceMonitorParams) (database.WorkspaceAgentVolumeResourceMonitor, error) { - if err := q.authorizeContext(ctx, policy.ActionCreate, rbac.ResourceWorkspaceAgentResourceMonitor); err != nil { - return database.WorkspaceAgentVolumeResourceMonitor{}, err - } + // if err := q.authorizeContext(ctx, policy.ActionCreate, rbac.ResourceWorkspaceAgentResourceMonitor); err != nil { + // return database.WorkspaceAgentVolumeResourceMonitor{}, err + // } return q.db.InsertVolumeResourceMonitor(ctx, arg) } diff --git a/coderd/database/modelmethods.go b/coderd/database/modelmethods.go index 63e03ccb27f40..a35d470e00475 100644 --- a/coderd/database/modelmethods.go +++ b/coderd/database/modelmethods.go @@ -327,6 +327,14 @@ func (c OAuth2ProviderAppCode) RBACObject() rbac.Object { return rbac.ResourceOauth2AppCodeToken.WithOwner(c.UserID.String()) } +func (c WorkspaceAgentMemoryResourceMonitor) RBACObject() rbac.Object { + return rbac.ResourceWorkspaceAgentResourceMonitor.RBACObject() +} + +func (c WorkspaceAgentVolumeResourceMonitor) RBACObject() rbac.Object { + return rbac.ResourceWorkspaceAgentResourceMonitor.RBACObject() +} + func (OAuth2ProviderAppSecret) RBACObject() rbac.Object { return rbac.ResourceOauth2AppSecret } diff --git a/coderd/workspaceagents_test.go b/coderd/workspaceagents_test.go index c75b3f3ed53fc..3319540c83a24 100644 --- a/coderd/workspaceagents_test.go +++ b/coderd/workspaceagents_test.go @@ -2041,7 +2041,7 @@ func requireGetManifest(ctx context.Context, t testing.TB, aAPI agentproto.DRPCA } func postStartup(ctx context.Context, t testing.TB, client agent.Client, startup *agentproto.Startup) error { - aAPI, _, err := client.ConnectRPC23(ctx) + aAPI, _, err := client.ConnectRPC24(ctx) require.NoError(t, err) defer func() { cErr := aAPI.DRPCConn().Close() From 0124d60cc877e9923a632373ab4c4659708f2a80 Mon Sep 17 00:00:00 2001 From: defelmnq Date: Mon, 10 Feb 2025 04:06:53 +0000 Subject: [PATCH 03/32] add missing files --- agent/resources_monitor.go | 121 +++++++++++++++++++++++++++++++ agent/resources_monitor_queue.go | 73 +++++++++++++++++++ 2 files changed, 194 insertions(+) create mode 100644 agent/resources_monitor.go create mode 100644 agent/resources_monitor_queue.go diff --git a/agent/resources_monitor.go b/agent/resources_monitor.go new file mode 100644 index 0000000000000..56fc718524b91 --- /dev/null +++ b/agent/resources_monitor.go @@ -0,0 +1,121 @@ +package agent + +import ( + "context" + "time" + + "golang.org/x/xerrors" + + "cdr.dev/slog" + "github.com/coder/coder/v2/agent/proto" + "github.com/coder/coder/v2/cli/clistat" + "github.com/coder/quartz" +) + +func (a *agent) pushResourcesMonitoring(ctx context.Context, aAPI proto.DRPCAgentClient24) error { + logger := a.logger.Named("resources_monitor") + + ctx, cancel := context.WithCancel(ctx) + defer cancel() + + config, err := aAPI.GetResourcesMonitoringConfiguration(ctx, &proto.GetResourcesMonitoringConfigurationRequest{}) + if err != nil { + return xerrors.Errorf("failed to get resources monitoring configuration: %w", err) + } + + if !config.Enabled { + logger.Info(ctx, "resources monitoring is disabled") + return nil + } + + clk := quartz.NewReal() + + resourcesFetcher, err := clistat.New() + if err != nil { + return xerrors.Errorf("failed to create resources fetcher: %w", err) + } + + datapointsQueue := newResourcesMonitorQueue(int(config.Config.NumDatapoints)) + + clk.TickerFunc(ctx, time.Duration(config.Config.TickInterval*int32(time.Second)), func() error { + memTotal, memUsed, err := fetchResourceMonitoredMemory(resourcesFetcher) + if err != nil { + logger.Error(ctx, "failed to fetch memory", slog.Error(err)) + return nil + } + + volumes := make([]*resourcesMonitor_VolumeDatapoint, 0, len(config.MonitoredVolumes)) + for _, volume := range config.MonitoredVolumes { + volTotal, volUsed, err := fetchResourceMonitoredVolume(resourcesFetcher, volume) + if err != nil { + logger.Error(ctx, "failed to fetch volume", slog.Error(err)) + return nil + } + + volumes = append(volumes, &resourcesMonitor_VolumeDatapoint{ + Path: volume, + Total: volTotal, + Used: volUsed, + }) + } + + datapointsQueue.Push(resourcesMonitor_Datapoint{ + Memory: &resourcesMonitor_MemoryDatapoint{ + Total: memTotal, + Used: memUsed, + }, + Volumes: volumes, + }) + + if datapointsQueue.IsFull() { + _, err = aAPI.PushResourcesMonitoringUsage(ctx, &proto.PushResourcesMonitoringUsageRequest{ + Datapoints: datapointsQueue.ItemsAsProto(), + }) + if err != nil { + logger.Error(ctx, "failed to push resources monitoring usage", slog.Error(err)) + } + } + + return nil + }, "resources_monitor") + + return nil +} + +func fetchResourceMonitoredMemory(fetcher *clistat.Statter) (int64, int64, error) { + mem, err := fetcher.HostMemory(clistat.PrefixMebi) + if err != nil { + return 0, 0, err + } + + var memTotal, memUsed int64 + if mem.Total == nil { + return 0, 0, xerrors.New("memory total is nil - can not fetch memory") + } + + memTotal = bytesToMegabytes(int64(*mem.Total)) + memUsed = bytesToMegabytes(int64(mem.Used)) + + return memTotal, memUsed, nil +} + +func fetchResourceMonitoredVolume(fetcher *clistat.Statter, volume string) (int64, int64, error) { + vol, err := fetcher.Disk(clistat.PrefixMebi, volume) + if err != nil { + return 0, 0, err + } + + var volTotal, volUsed int64 + if vol.Total == nil { + return 0, 0, xerrors.New("volume total is nil - can not fetch volume") + } + + volTotal = bytesToMegabytes(int64(*vol.Total)) + volUsed = bytesToMegabytes(int64(vol.Used)) + + return volTotal, volUsed, nil +} + +func bytesToMegabytes(bytes int64) int64 { + return bytes / (1024 * 1024) +} diff --git a/agent/resources_monitor_queue.go b/agent/resources_monitor_queue.go new file mode 100644 index 0000000000000..e3d1e8fa9a6f5 --- /dev/null +++ b/agent/resources_monitor_queue.go @@ -0,0 +1,73 @@ +package agent + +import ( + "github.com/coder/coder/v2/agent/proto" +) + +type resourcesMonitor_Datapoint struct { + Memory *resourcesMonitor_MemoryDatapoint + Volumes []*resourcesMonitor_VolumeDatapoint +} + +type resourcesMonitor_MemoryDatapoint struct { + Total int64 + Used int64 +} + +type resourcesMonitor_VolumeDatapoint struct { + Path string + Total int64 + Used int64 +} + +// resourcesMonitorQueue represents a FIFO queue with a fixed size +type resourcesMonitorQueue struct { + items []resourcesMonitor_Datapoint + size int +} + +// newResourcesMonitorQueue creates a new resourcesMonitorQueue with the given size +func newResourcesMonitorQueue(size int) *resourcesMonitorQueue { + return &resourcesMonitorQueue{ + items: make([]resourcesMonitor_Datapoint, 0, size), + size: size, + } +} + +// Push adds a new item to the queue +func (q *resourcesMonitorQueue) Push(item resourcesMonitor_Datapoint) { + if len(q.items) >= q.size { + // Remove the first item (FIFO) + q.items = q.items[1:] + } + q.items = append(q.items, item) +} + +func (q *resourcesMonitorQueue) IsFull() bool { + return len(q.items) == q.size +} + +func (q *resourcesMonitorQueue) ItemsAsProto() []*proto.PushResourcesMonitoringUsageRequest_Datapoint { + items := make([]*proto.PushResourcesMonitoringUsageRequest_Datapoint, 0, len(q.items)) + + for _, item := range q.items { + protoItem := &proto.PushResourcesMonitoringUsageRequest_Datapoint{ + Memory: &proto.PushResourcesMonitoringUsageRequest_Datapoint_MemoryUsage{ + Total: item.Memory.Total, + Used: item.Memory.Used, + }, + } + + for _, volume := range item.Volumes { + protoItem.Volumes = append(protoItem.Volumes, &proto.PushResourcesMonitoringUsageRequest_Datapoint_VolumeUsage{ + Volume: volume.Path, + Total: volume.Total, + Used: volume.Used, + }) + } + + items = append(items, protoItem) + } + + return items +} From 3661e8c72bc8bd2adf33aac9e9b93ff08c8baffa Mon Sep 17 00:00:00 2001 From: defelmnq Date: Tue, 11 Feb 2025 02:06:23 +0000 Subject: [PATCH 04/32] work on resources monitor tests --- agent/resources_monitor.go | 32 ++++--- agent/resources_monitor_queue.go | 20 +++-- agent/resources_monitor_queue_test.go | 100 +++++++++++++++++++++ agent/resources_monitor_test.go | 124 ++++++++++++++++++++++++++ 4 files changed, 258 insertions(+), 18 deletions(-) create mode 100644 agent/resources_monitor_queue_test.go create mode 100644 agent/resources_monitor_test.go diff --git a/agent/resources_monitor.go b/agent/resources_monitor.go index 56fc718524b91..a363c08ad6498 100644 --- a/agent/resources_monitor.go +++ b/agent/resources_monitor.go @@ -18,7 +18,21 @@ func (a *agent) pushResourcesMonitoring(ctx context.Context, aAPI proto.DRPCAgen ctx, cancel := context.WithCancel(ctx) defer cancel() - config, err := aAPI.GetResourcesMonitoringConfiguration(ctx, &proto.GetResourcesMonitoringConfigurationRequest{}) + clk := quartz.NewReal() + + return pushResourcesMonitoringWithConfig(ctx, logger, clk, aAPI.GetResourcesMonitoringConfiguration, aAPI.PushResourcesMonitoringUsage) +} + +type resourcesMonitorConfigurationFetcher func(ctx context.Context, params *proto.GetResourcesMonitoringConfigurationRequest) (*proto.GetResourcesMonitoringConfigurationResponse, error) +type resourcesMonitorDatapointsPusher func(ctx context.Context, params *proto.PushResourcesMonitoringUsageRequest) (*proto.PushResourcesMonitoringUsageResponse, error) + +func pushResourcesMonitoringWithConfig(ctx context.Context, + logger slog.Logger, + clk quartz.Clock, + configFetcher resourcesMonitorConfigurationFetcher, + datapointsPusher resourcesMonitorDatapointsPusher, +) error { + config, err := configFetcher(ctx, &proto.GetResourcesMonitoringConfigurationRequest{}) if err != nil { return xerrors.Errorf("failed to get resources monitoring configuration: %w", err) } @@ -28,8 +42,6 @@ func (a *agent) pushResourcesMonitoring(ctx context.Context, aAPI proto.DRPCAgen return nil } - clk := quartz.NewReal() - resourcesFetcher, err := clistat.New() if err != nil { return xerrors.Errorf("failed to create resources fetcher: %w", err) @@ -44,7 +56,7 @@ func (a *agent) pushResourcesMonitoring(ctx context.Context, aAPI proto.DRPCAgen return nil } - volumes := make([]*resourcesMonitor_VolumeDatapoint, 0, len(config.MonitoredVolumes)) + volumes := make([]*resourcesMonitorVolumeDatapoint, 0, len(config.MonitoredVolumes)) for _, volume := range config.MonitoredVolumes { volTotal, volUsed, err := fetchResourceMonitoredVolume(resourcesFetcher, volume) if err != nil { @@ -52,15 +64,15 @@ func (a *agent) pushResourcesMonitoring(ctx context.Context, aAPI proto.DRPCAgen return nil } - volumes = append(volumes, &resourcesMonitor_VolumeDatapoint{ + volumes = append(volumes, &resourcesMonitorVolumeDatapoint{ Path: volume, Total: volTotal, Used: volUsed, }) } - datapointsQueue.Push(resourcesMonitor_Datapoint{ - Memory: &resourcesMonitor_MemoryDatapoint{ + datapointsQueue.Push(resourcesMonitorDatapoint{ + Memory: &resourcesMonitorMemoryDatapoint{ Total: memTotal, Used: memUsed, }, @@ -68,7 +80,7 @@ func (a *agent) pushResourcesMonitoring(ctx context.Context, aAPI proto.DRPCAgen }) if datapointsQueue.IsFull() { - _, err = aAPI.PushResourcesMonitoringUsage(ctx, &proto.PushResourcesMonitoringUsageRequest{ + _, err = datapointsPusher(ctx, &proto.PushResourcesMonitoringUsageRequest{ Datapoints: datapointsQueue.ItemsAsProto(), }) if err != nil { @@ -82,7 +94,7 @@ func (a *agent) pushResourcesMonitoring(ctx context.Context, aAPI proto.DRPCAgen return nil } -func fetchResourceMonitoredMemory(fetcher *clistat.Statter) (int64, int64, error) { +func fetchResourceMonitoredMemory(fetcher *clistat.Statter) (total int64, used int64, err error) { mem, err := fetcher.HostMemory(clistat.PrefixMebi) if err != nil { return 0, 0, err @@ -99,7 +111,7 @@ func fetchResourceMonitoredMemory(fetcher *clistat.Statter) (int64, int64, error return memTotal, memUsed, nil } -func fetchResourceMonitoredVolume(fetcher *clistat.Statter, volume string) (int64, int64, error) { +func fetchResourceMonitoredVolume(fetcher *clistat.Statter, volume string) (total int64, used int64, err error) { vol, err := fetcher.Disk(clistat.PrefixMebi, volume) if err != nil { return 0, 0, err diff --git a/agent/resources_monitor_queue.go b/agent/resources_monitor_queue.go index e3d1e8fa9a6f5..0b11e542607e5 100644 --- a/agent/resources_monitor_queue.go +++ b/agent/resources_monitor_queue.go @@ -4,17 +4,17 @@ import ( "github.com/coder/coder/v2/agent/proto" ) -type resourcesMonitor_Datapoint struct { - Memory *resourcesMonitor_MemoryDatapoint - Volumes []*resourcesMonitor_VolumeDatapoint +type resourcesMonitorDatapoint struct { + Memory *resourcesMonitorMemoryDatapoint + Volumes []*resourcesMonitorVolumeDatapoint } -type resourcesMonitor_MemoryDatapoint struct { +type resourcesMonitorMemoryDatapoint struct { Total int64 Used int64 } -type resourcesMonitor_VolumeDatapoint struct { +type resourcesMonitorVolumeDatapoint struct { Path string Total int64 Used int64 @@ -22,20 +22,20 @@ type resourcesMonitor_VolumeDatapoint struct { // resourcesMonitorQueue represents a FIFO queue with a fixed size type resourcesMonitorQueue struct { - items []resourcesMonitor_Datapoint + items []resourcesMonitorDatapoint size int } // newResourcesMonitorQueue creates a new resourcesMonitorQueue with the given size func newResourcesMonitorQueue(size int) *resourcesMonitorQueue { return &resourcesMonitorQueue{ - items: make([]resourcesMonitor_Datapoint, 0, size), + items: make([]resourcesMonitorDatapoint, 0, size), size: size, } } // Push adds a new item to the queue -func (q *resourcesMonitorQueue) Push(item resourcesMonitor_Datapoint) { +func (q *resourcesMonitorQueue) Push(item resourcesMonitorDatapoint) { if len(q.items) >= q.size { // Remove the first item (FIFO) q.items = q.items[1:] @@ -47,6 +47,10 @@ func (q *resourcesMonitorQueue) IsFull() bool { return len(q.items) == q.size } +func (q *resourcesMonitorQueue) Items() []resourcesMonitorDatapoint { + return q.items +} + func (q *resourcesMonitorQueue) ItemsAsProto() []*proto.PushResourcesMonitoringUsageRequest_Datapoint { items := make([]*proto.PushResourcesMonitoringUsageRequest_Datapoint, 0, len(q.items)) diff --git a/agent/resources_monitor_queue_test.go b/agent/resources_monitor_queue_test.go new file mode 100644 index 0000000000000..50d65a4ec4d9c --- /dev/null +++ b/agent/resources_monitor_queue_test.go @@ -0,0 +1,100 @@ +package agent + +import ( + "testing" +) + +func TestResourceMonitorQueue(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + pushCount int + expected []resourcesMonitorDatapoint + }{ + { + name: "Push zero", + pushCount: 0, + expected: []resourcesMonitorDatapoint{}, + }, + { + name: "Push less than capacity", + pushCount: 3, + expected: []resourcesMonitorDatapoint{ + {Memory: &resourcesMonitorMemoryDatapoint{Total: 1, Used: 1}}, + {Memory: &resourcesMonitorMemoryDatapoint{Total: 2, Used: 2}}, + {Memory: &resourcesMonitorMemoryDatapoint{Total: 3, Used: 3}}, + }, + }, + { + name: "Push exactly capacity", + pushCount: 20, + expected: func() []resourcesMonitorDatapoint { + var result []resourcesMonitorDatapoint + for i := 1; i <= 20; i++ { + result = append(result, resourcesMonitorDatapoint{ + Memory: &resourcesMonitorMemoryDatapoint{ + Total: int64(i), + Used: int64(i), + }, + }) + } + return result + }(), + }, + { + name: "Push more than capacity", + pushCount: 25, + expected: func() []resourcesMonitorDatapoint { + var result []resourcesMonitorDatapoint + for i := 6; i <= 25; i++ { + result = append(result, resourcesMonitorDatapoint{ + Memory: &resourcesMonitorMemoryDatapoint{ + Total: int64(i), + Used: int64(i), + }, + }) + } + return result + }(), + }, + } + + for _, tt := range tests { + tt := tt + + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + queue := newResourcesMonitorQueue(20) + for i := 1; i <= tt.pushCount; i++ { + queue.Push(resourcesMonitorDatapoint{ + Memory: &resourcesMonitorMemoryDatapoint{ + Total: int64(i), + Used: int64(i), + }, + }) + } + if tt.pushCount < 20 && queue.IsFull() { + t.Errorf("expected %v, got %v", false, queue.IsFull()) + } + if tt.pushCount >= 20 && len(queue.Items()) != 20 { + t.Errorf("expected %v, got %v", 20, tt.pushCount) + } + if got := queue.Items(); !equal(got, tt.expected) { + t.Errorf("expected %v, got %v", tt.expected, got) + } + }) + } +} + +func equal(a, b []resourcesMonitorDatapoint) bool { + if len(a) != len(b) { + return false + } + for i := range a { + if a[i].Memory.Total != b[i].Memory.Total || a[i].Memory.Used != b[i].Memory.Used { + return false + } + } + return true +} diff --git a/agent/resources_monitor_test.go b/agent/resources_monitor_test.go new file mode 100644 index 0000000000000..c654dd6a9180d --- /dev/null +++ b/agent/resources_monitor_test.go @@ -0,0 +1,124 @@ +package agent + +import ( + "context" + "os" + "testing" + + "cdr.dev/slog" + "cdr.dev/slog/sloggers/sloghuman" + "github.com/coder/coder/v2/agent/proto" + "github.com/coder/quartz" +) + +func TestPushResourcesMonitoringWithConfig(t *testing.T) { + t.Parallel() + + tests := []struct { + name string + configFetcher resourcesMonitorConfigurationFetcher + datapointsPusher resourcesMonitorDatapointsPusher + expectedError bool + numTicks int + counterCalls int + expectedCalls int + }{ + { + name: "Successful monitoring", + configFetcher: func(_ context.Context, params *proto.GetResourcesMonitoringConfigurationRequest) (*proto.GetResourcesMonitoringConfigurationResponse, error) { + return &proto.GetResourcesMonitoringConfigurationResponse{ + Enabled: true, + Config: &proto.GetResourcesMonitoringConfigurationResponse_Config{ + NumDatapoints: 20, + TickInterval: 1, + }, + MonitoredVolumes: []string{"/"}, + }, nil + }, + datapointsPusher: func(_ context.Context, params *proto.PushResourcesMonitoringUsageRequest) (*proto.PushResourcesMonitoringUsageResponse, error) { + return &proto.PushResourcesMonitoringUsageResponse{}, nil + }, + expectedError: false, + numTicks: 20, + counterCalls: 0, + expectedCalls: 1, + }, + // { + // name: "Disabled monitoring", + // configFetcher: func(ctx context.Context, params *proto.GetResourcesMonitoringConfigurationRequest) (*proto.GetResourcesMonitoringConfigurationResponse, error) { + // return &proto.GetResourcesMonitoringConfigurationResponse{ + // Enabled: false, + // }, nil + // }, + // datapointsPusher: func(ctx context.Context, params *proto.PushResourcesMonitoringUsageRequest) (*proto.PushResourcesMonitoringUsageResponse, error) { + // return &proto.PushResourcesMonitoringUsageResponse{}, nil + // }, + // expectedError: false, + // expectedCalls: 0, + // }, + // { + // name: "Failed to fetch configuration", + // configFetcher: func(ctx context.Context, params *proto.GetResourcesMonitoringConfigurationRequest) (*proto.GetResourcesMonitoringConfigurationResponse, error) { + // return nil, xerrors.New("failed to fetch configuration") + // }, + // datapointsPusher: func(ctx context.Context, params *proto.PushResourcesMonitoringUsageRequest) (*proto.PushResourcesMonitoringUsageResponse, error) { + // return &proto.PushResourcesMonitoringUsageResponse{}, nil + // }, + // expectedError: true, + // expectedCalls: 0, + // }, + // { + // name: "Failed to push datapoints", + // configFetcher: func(ctx context.Context, params *proto.GetResourcesMonitoringConfigurationRequest) (*proto.GetResourcesMonitoringConfigurationResponse, error) { + // return &proto.GetResourcesMonitoringConfigurationResponse{ + // Enabled: true, + // Config: &proto.GetResourcesMonitoringConfigurationResponse_Config{ + // NumDatapoints: 1, + // TickInterval: 1, + // }, + // MonitoredVolumes: []string{"/"}, + // }, nil + // }, + // datapointsPusher: func(ctx context.Context, params *proto.PushResourcesMonitoringUsageRequest) (*proto.PushResourcesMonitoringUsageResponse, error) { + // return nil, xerrors.New("failed to push datapoints") + // }, + // expectedError: true, + // expectedCalls: 1, + // }, + } + + for _, tt := range tests { + tt := tt + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + clk := quartz.NewMock(t) + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + logger := slog.Make(sloghuman.Sink(os.Stdout)) + + datapointsPusher := func(ctx context.Context, params *proto.PushResourcesMonitoringUsageRequest) (*proto.PushResourcesMonitoringUsageResponse, error) { + tt.counterCalls++ + t.Logf("pushing datapoints: %v", tt.counterCalls) + return tt.datapointsPusher(ctx, params) + } + + err := pushResourcesMonitoringWithConfig(ctx, logger, clk, tt.configFetcher, datapointsPusher) + if (err != nil) != tt.expectedError { + t.Errorf("expected error: %v, got: %v", tt.expectedError, err) + } + + for i := 0; i < tt.numTicks; i++ { + _, waiter := clk.AdvanceNext() + waiter.Wait(ctx) + } + + if tt.counterCalls != tt.expectedCalls { + t.Errorf("expected call count: %v, got: %v", tt.expectedCalls, tt.counterCalls) + } + + cancel() + }) + } +} From a5a788e801d39a5ceb61123c7207cf585445f429 Mon Sep 17 00:00:00 2001 From: defelmnq Date: Tue, 11 Feb 2025 02:21:52 +0000 Subject: [PATCH 05/32] apply fmt and lint --- agent/agenttest/client.go | 4 +-- agent/resources_monitor.go | 24 ++++++++-------- agent/resources_monitor_queue.go | 32 ++++++++++----------- agent/resources_monitor_queue_test.go | 40 ++++++++++++++------------- agent/resources_monitor_test.go | 9 +++--- coderd/database/modelmethods.go | 4 +-- 6 files changed, 59 insertions(+), 54 deletions(-) diff --git a/agent/agenttest/client.go b/agent/agenttest/client.go index e07cf1a2732ab..c530c8e6a79e9 100644 --- a/agent/agenttest/client.go +++ b/agent/agenttest/client.go @@ -214,7 +214,7 @@ func (f *FakeAgentAPI) GetAnnouncementBanners(context.Context, *agentproto.GetAn return &agentproto.GetAnnouncementBannersResponse{AnnouncementBanners: bannersProto}, nil } -func (f *FakeAgentAPI) GetResourcesMonitoringConfiguration(ctx context.Context, req *agentproto.GetResourcesMonitoringConfigurationRequest) (*agentproto.GetResourcesMonitoringConfigurationResponse, error) { +func (f *FakeAgentAPI) GetResourcesMonitoringConfiguration(_ context.Context, _ *agentproto.GetResourcesMonitoringConfigurationRequest) (*agentproto.GetResourcesMonitoringConfigurationResponse, error) { f.Lock() defer f.Unlock() @@ -225,7 +225,7 @@ func (f *FakeAgentAPI) GetResourcesMonitoringConfiguration(ctx context.Context, return f.getResourcesMonitoringConfigurationFunc() } -func (f *FakeAgentAPI) PushResourcesMonitoringUsage(ctx context.Context, req *agentproto.PushResourcesMonitoringUsageRequest) (*agentproto.PushResourcesMonitoringUsageResponse, error) { +func (f *FakeAgentAPI) PushResourcesMonitoringUsage(_ context.Context, req *agentproto.PushResourcesMonitoringUsageRequest) (*agentproto.PushResourcesMonitoringUsageResponse, error) { f.Lock() defer f.Unlock() diff --git a/agent/resources_monitor.go b/agent/resources_monitor.go index a363c08ad6498..6f68135f2bb8a 100644 --- a/agent/resources_monitor.go +++ b/agent/resources_monitor.go @@ -20,17 +20,19 @@ func (a *agent) pushResourcesMonitoring(ctx context.Context, aAPI proto.DRPCAgen clk := quartz.NewReal() - return pushResourcesMonitoringWithConfig(ctx, logger, clk, aAPI.GetResourcesMonitoringConfiguration, aAPI.PushResourcesMonitoringUsage) + return PushResourcesMonitoringWithConfig(ctx, logger, clk, aAPI.GetResourcesMonitoringConfiguration, aAPI.PushResourcesMonitoringUsage) } -type resourcesMonitorConfigurationFetcher func(ctx context.Context, params *proto.GetResourcesMonitoringConfigurationRequest) (*proto.GetResourcesMonitoringConfigurationResponse, error) -type resourcesMonitorDatapointsPusher func(ctx context.Context, params *proto.PushResourcesMonitoringUsageRequest) (*proto.PushResourcesMonitoringUsageResponse, error) +type ( + ResourcesMonitorConfigurationFetcher func(ctx context.Context, params *proto.GetResourcesMonitoringConfigurationRequest) (*proto.GetResourcesMonitoringConfigurationResponse, error) + ResourcesMonitorDatapointsPusher func(ctx context.Context, params *proto.PushResourcesMonitoringUsageRequest) (*proto.PushResourcesMonitoringUsageResponse, error) +) -func pushResourcesMonitoringWithConfig(ctx context.Context, +func PushResourcesMonitoringWithConfig(ctx context.Context, logger slog.Logger, clk quartz.Clock, - configFetcher resourcesMonitorConfigurationFetcher, - datapointsPusher resourcesMonitorDatapointsPusher, + configFetcher ResourcesMonitorConfigurationFetcher, + datapointsPusher ResourcesMonitorDatapointsPusher, ) error { config, err := configFetcher(ctx, &proto.GetResourcesMonitoringConfigurationRequest{}) if err != nil { @@ -47,7 +49,7 @@ func pushResourcesMonitoringWithConfig(ctx context.Context, return xerrors.Errorf("failed to create resources fetcher: %w", err) } - datapointsQueue := newResourcesMonitorQueue(int(config.Config.NumDatapoints)) + datapointsQueue := NewResourcesMonitorQueue(int(config.Config.NumDatapoints)) clk.TickerFunc(ctx, time.Duration(config.Config.TickInterval*int32(time.Second)), func() error { memTotal, memUsed, err := fetchResourceMonitoredMemory(resourcesFetcher) @@ -56,7 +58,7 @@ func pushResourcesMonitoringWithConfig(ctx context.Context, return nil } - volumes := make([]*resourcesMonitorVolumeDatapoint, 0, len(config.MonitoredVolumes)) + volumes := make([]*ResourcesMonitorVolumeDatapoint, 0, len(config.MonitoredVolumes)) for _, volume := range config.MonitoredVolumes { volTotal, volUsed, err := fetchResourceMonitoredVolume(resourcesFetcher, volume) if err != nil { @@ -64,15 +66,15 @@ func pushResourcesMonitoringWithConfig(ctx context.Context, return nil } - volumes = append(volumes, &resourcesMonitorVolumeDatapoint{ + volumes = append(volumes, &ResourcesMonitorVolumeDatapoint{ Path: volume, Total: volTotal, Used: volUsed, }) } - datapointsQueue.Push(resourcesMonitorDatapoint{ - Memory: &resourcesMonitorMemoryDatapoint{ + datapointsQueue.Push(ResourcesMonitorDatapoint{ + Memory: &ResourcesMonitorMemoryDatapoint{ Total: memTotal, Used: memUsed, }, diff --git a/agent/resources_monitor_queue.go b/agent/resources_monitor_queue.go index 0b11e542607e5..1046ab9e6515e 100644 --- a/agent/resources_monitor_queue.go +++ b/agent/resources_monitor_queue.go @@ -4,38 +4,38 @@ import ( "github.com/coder/coder/v2/agent/proto" ) -type resourcesMonitorDatapoint struct { - Memory *resourcesMonitorMemoryDatapoint - Volumes []*resourcesMonitorVolumeDatapoint +type ResourcesMonitorDatapoint struct { + Memory *ResourcesMonitorMemoryDatapoint + Volumes []*ResourcesMonitorVolumeDatapoint } -type resourcesMonitorMemoryDatapoint struct { +type ResourcesMonitorMemoryDatapoint struct { Total int64 Used int64 } -type resourcesMonitorVolumeDatapoint struct { +type ResourcesMonitorVolumeDatapoint struct { Path string Total int64 Used int64 } -// resourcesMonitorQueue represents a FIFO queue with a fixed size -type resourcesMonitorQueue struct { - items []resourcesMonitorDatapoint +// ResourcesMonitorQueue represents a FIFO queue with a fixed size +type ResourcesMonitorQueue struct { + items []ResourcesMonitorDatapoint size int } -// newResourcesMonitorQueue creates a new resourcesMonitorQueue with the given size -func newResourcesMonitorQueue(size int) *resourcesMonitorQueue { - return &resourcesMonitorQueue{ - items: make([]resourcesMonitorDatapoint, 0, size), +// newResourcesMonitorQueue creates a new ResourcesMonitorQueue with the given size +func NewResourcesMonitorQueue(size int) *ResourcesMonitorQueue { + return &ResourcesMonitorQueue{ + items: make([]ResourcesMonitorDatapoint, 0, size), size: size, } } // Push adds a new item to the queue -func (q *resourcesMonitorQueue) Push(item resourcesMonitorDatapoint) { +func (q *ResourcesMonitorQueue) Push(item ResourcesMonitorDatapoint) { if len(q.items) >= q.size { // Remove the first item (FIFO) q.items = q.items[1:] @@ -43,15 +43,15 @@ func (q *resourcesMonitorQueue) Push(item resourcesMonitorDatapoint) { q.items = append(q.items, item) } -func (q *resourcesMonitorQueue) IsFull() bool { +func (q *ResourcesMonitorQueue) IsFull() bool { return len(q.items) == q.size } -func (q *resourcesMonitorQueue) Items() []resourcesMonitorDatapoint { +func (q *ResourcesMonitorQueue) Items() []ResourcesMonitorDatapoint { return q.items } -func (q *resourcesMonitorQueue) ItemsAsProto() []*proto.PushResourcesMonitoringUsageRequest_Datapoint { +func (q *ResourcesMonitorQueue) ItemsAsProto() []*proto.PushResourcesMonitoringUsageRequest_Datapoint { items := make([]*proto.PushResourcesMonitoringUsageRequest_Datapoint, 0, len(q.items)) for _, item := range q.items { diff --git a/agent/resources_monitor_queue_test.go b/agent/resources_monitor_queue_test.go index 50d65a4ec4d9c..079c0f62c672b 100644 --- a/agent/resources_monitor_queue_test.go +++ b/agent/resources_monitor_queue_test.go @@ -1,7 +1,9 @@ -package agent +package agent_test import ( "testing" + + "github.com/coder/coder/v2/agent" ) func TestResourceMonitorQueue(t *testing.T) { @@ -10,30 +12,30 @@ func TestResourceMonitorQueue(t *testing.T) { tests := []struct { name string pushCount int - expected []resourcesMonitorDatapoint + expected []agent.ResourcesMonitorDatapoint }{ { name: "Push zero", pushCount: 0, - expected: []resourcesMonitorDatapoint{}, + expected: []agent.ResourcesMonitorDatapoint{}, }, { name: "Push less than capacity", pushCount: 3, - expected: []resourcesMonitorDatapoint{ - {Memory: &resourcesMonitorMemoryDatapoint{Total: 1, Used: 1}}, - {Memory: &resourcesMonitorMemoryDatapoint{Total: 2, Used: 2}}, - {Memory: &resourcesMonitorMemoryDatapoint{Total: 3, Used: 3}}, + expected: []agent.ResourcesMonitorDatapoint{ + {Memory: &agent.ResourcesMonitorMemoryDatapoint{Total: 1, Used: 1}}, + {Memory: &agent.ResourcesMonitorMemoryDatapoint{Total: 2, Used: 2}}, + {Memory: &agent.ResourcesMonitorMemoryDatapoint{Total: 3, Used: 3}}, }, }, { name: "Push exactly capacity", pushCount: 20, - expected: func() []resourcesMonitorDatapoint { - var result []resourcesMonitorDatapoint + expected: func() []agent.ResourcesMonitorDatapoint { + var result []agent.ResourcesMonitorDatapoint for i := 1; i <= 20; i++ { - result = append(result, resourcesMonitorDatapoint{ - Memory: &resourcesMonitorMemoryDatapoint{ + result = append(result, agent.ResourcesMonitorDatapoint{ + Memory: &agent.ResourcesMonitorMemoryDatapoint{ Total: int64(i), Used: int64(i), }, @@ -45,11 +47,11 @@ func TestResourceMonitorQueue(t *testing.T) { { name: "Push more than capacity", pushCount: 25, - expected: func() []resourcesMonitorDatapoint { - var result []resourcesMonitorDatapoint + expected: func() []agent.ResourcesMonitorDatapoint { + var result []agent.ResourcesMonitorDatapoint for i := 6; i <= 25; i++ { - result = append(result, resourcesMonitorDatapoint{ - Memory: &resourcesMonitorMemoryDatapoint{ + result = append(result, agent.ResourcesMonitorDatapoint{ + Memory: &agent.ResourcesMonitorMemoryDatapoint{ Total: int64(i), Used: int64(i), }, @@ -65,10 +67,10 @@ func TestResourceMonitorQueue(t *testing.T) { t.Run(tt.name, func(t *testing.T) { t.Parallel() - queue := newResourcesMonitorQueue(20) + queue := agent.NewResourcesMonitorQueue(20) for i := 1; i <= tt.pushCount; i++ { - queue.Push(resourcesMonitorDatapoint{ - Memory: &resourcesMonitorMemoryDatapoint{ + queue.Push(agent.ResourcesMonitorDatapoint{ + Memory: &agent.ResourcesMonitorMemoryDatapoint{ Total: int64(i), Used: int64(i), }, @@ -87,7 +89,7 @@ func TestResourceMonitorQueue(t *testing.T) { } } -func equal(a, b []resourcesMonitorDatapoint) bool { +func equal(a, b []agent.ResourcesMonitorDatapoint) bool { if len(a) != len(b) { return false } diff --git a/agent/resources_monitor_test.go b/agent/resources_monitor_test.go index c654dd6a9180d..45d7a886b2867 100644 --- a/agent/resources_monitor_test.go +++ b/agent/resources_monitor_test.go @@ -1,4 +1,4 @@ -package agent +package agent_test import ( "context" @@ -7,6 +7,7 @@ import ( "cdr.dev/slog" "cdr.dev/slog/sloggers/sloghuman" + "github.com/coder/coder/v2/agent" "github.com/coder/coder/v2/agent/proto" "github.com/coder/quartz" ) @@ -16,8 +17,8 @@ func TestPushResourcesMonitoringWithConfig(t *testing.T) { tests := []struct { name string - configFetcher resourcesMonitorConfigurationFetcher - datapointsPusher resourcesMonitorDatapointsPusher + configFetcher agent.ResourcesMonitorConfigurationFetcher + datapointsPusher agent.ResourcesMonitorDatapointsPusher expectedError bool numTicks int counterCalls int @@ -104,7 +105,7 @@ func TestPushResourcesMonitoringWithConfig(t *testing.T) { return tt.datapointsPusher(ctx, params) } - err := pushResourcesMonitoringWithConfig(ctx, logger, clk, tt.configFetcher, datapointsPusher) + err := agent.PushResourcesMonitoringWithConfig(ctx, logger, clk, tt.configFetcher, datapointsPusher) if (err != nil) != tt.expectedError { t.Errorf("expected error: %v, got: %v", tt.expectedError, err) } diff --git a/coderd/database/modelmethods.go b/coderd/database/modelmethods.go index a35d470e00475..0752ed1f2942d 100644 --- a/coderd/database/modelmethods.go +++ b/coderd/database/modelmethods.go @@ -327,11 +327,11 @@ func (c OAuth2ProviderAppCode) RBACObject() rbac.Object { return rbac.ResourceOauth2AppCodeToken.WithOwner(c.UserID.String()) } -func (c WorkspaceAgentMemoryResourceMonitor) RBACObject() rbac.Object { +func (WorkspaceAgentMemoryResourceMonitor) RBACObject() rbac.Object { return rbac.ResourceWorkspaceAgentResourceMonitor.RBACObject() } -func (c WorkspaceAgentVolumeResourceMonitor) RBACObject() rbac.Object { +func (WorkspaceAgentVolumeResourceMonitor) RBACObject() rbac.Object { return rbac.ResourceWorkspaceAgentResourceMonitor.RBACObject() } From 91d1515558f2adbb7bad2f5a3f40cf432eb89f01 Mon Sep 17 00:00:00 2001 From: defelmnq Date: Tue, 11 Feb 2025 02:33:59 +0000 Subject: [PATCH 06/32] work on dbauthz tests --- coderd/database/dbauthz/dbauthz.go | 24 ++++++++++++------------ coderd/database/dbauthz/dbauthz_test.go | 8 ++++---- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/coderd/database/dbauthz/dbauthz.go b/coderd/database/dbauthz/dbauthz.go index 7d5f020010ea2..d32ec23e9e7ef 100644 --- a/coderd/database/dbauthz/dbauthz.go +++ b/coderd/database/dbauthz/dbauthz.go @@ -1392,9 +1392,9 @@ func (q *querier) FavoriteWorkspace(ctx context.Context, id uuid.UUID) error { } func (q *querier) FetchMemoryResourceMonitorsByAgentID(ctx context.Context, agentID uuid.UUID) (database.WorkspaceAgentMemoryResourceMonitor, error) { - // if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceWorkspaceAgentResourceMonitor); err != nil { - // return database.WorkspaceAgentMemoryResourceMonitor{}, err - // } + if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceSystem); err != nil { + return database.WorkspaceAgentMemoryResourceMonitor{}, err + } return q.db.FetchMemoryResourceMonitorsByAgentID(ctx, agentID) } @@ -1407,9 +1407,9 @@ func (q *querier) FetchNewMessageMetadata(ctx context.Context, arg database.Fetc } func (q *querier) FetchVolumesResourceMonitorsByAgentID(ctx context.Context, agentID uuid.UUID) ([]database.WorkspaceAgentVolumeResourceMonitor, error) { - // if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceWorkspaceAgentResourceMonitor); err != nil { - // return nil, err - // } + if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceSystem); err != nil { + return nil, err + } return q.db.FetchVolumesResourceMonitorsByAgentID(ctx, agentID) } @@ -3020,9 +3020,9 @@ func (q *querier) InsertLicense(ctx context.Context, arg database.InsertLicenseP } func (q *querier) InsertMemoryResourceMonitor(ctx context.Context, arg database.InsertMemoryResourceMonitorParams) (database.WorkspaceAgentMemoryResourceMonitor, error) { - // if err := q.authorizeContext(ctx, policy.ActionCreate, rbac.ResourceWorkspaceAgentResourceMonitor); err != nil { - // return database.WorkspaceAgentMemoryResourceMonitor{}, err - // } + if err := q.authorizeContext(ctx, policy.ActionCreate, rbac.ResourceSystem); err != nil { + return database.WorkspaceAgentMemoryResourceMonitor{}, err + } return q.db.InsertMemoryResourceMonitor(ctx, arg) } @@ -3220,9 +3220,9 @@ func (q *querier) InsertUserLink(ctx context.Context, arg database.InsertUserLin } func (q *querier) InsertVolumeResourceMonitor(ctx context.Context, arg database.InsertVolumeResourceMonitorParams) (database.WorkspaceAgentVolumeResourceMonitor, error) { - // if err := q.authorizeContext(ctx, policy.ActionCreate, rbac.ResourceWorkspaceAgentResourceMonitor); err != nil { - // return database.WorkspaceAgentVolumeResourceMonitor{}, err - // } + if err := q.authorizeContext(ctx, policy.ActionCreate, rbac.ResourceSystem); err != nil { + return database.WorkspaceAgentVolumeResourceMonitor{}, err + } return q.db.InsertVolumeResourceMonitor(ctx, arg) } diff --git a/coderd/database/dbauthz/dbauthz_test.go b/coderd/database/dbauthz/dbauthz_test.go index e99bc37271c16..cdcae62d505c6 100644 --- a/coderd/database/dbauthz/dbauthz_test.go +++ b/coderd/database/dbauthz/dbauthz_test.go @@ -4566,12 +4566,12 @@ func (s *MethodTestSuite) TestOAuth2ProviderAppTokens() { func (s *MethodTestSuite) TestResourcesMonitor() { s.Run("InsertMemoryResourceMonitor", s.Subtest(func(db database.Store, check *expects) { dbtestutil.DisableForeignKeysAndTriggers(s.T(), db) - check.Args(database.InsertMemoryResourceMonitorParams{}).Asserts(rbac.ResourceWorkspaceAgentResourceMonitor, policy.ActionCreate) + check.Args(database.InsertMemoryResourceMonitorParams{}).Asserts(rbac.ResourceSystem, policy.ActionCreate) })) s.Run("InsertVolumeResourceMonitor", s.Subtest(func(db database.Store, check *expects) { dbtestutil.DisableForeignKeysAndTriggers(s.T(), db) - check.Args(database.InsertVolumeResourceMonitorParams{}).Asserts(rbac.ResourceWorkspaceAgentResourceMonitor, policy.ActionCreate) + check.Args(database.InsertVolumeResourceMonitorParams{}).Asserts(rbac.ResourceSystem, policy.ActionCreate) })) s.Run("FetchMemoryResourceMonitorsByAgentID", s.Subtest(func(db database.Store, check *expects) { @@ -4611,7 +4611,7 @@ func (s *MethodTestSuite) TestResourcesMonitor() { monitor, err := db.FetchMemoryResourceMonitorsByAgentID(context.Background(), agt.ID) require.NoError(s.T(), err) - check.Args(agt.ID).Asserts(rbac.ResourceWorkspaceAgentResourceMonitor, policy.ActionRead).Returns(monitor) + check.Args(agt.ID).Asserts(rbac.ResourceSystem, policy.ActionRead).Returns(monitor) })) s.Run("FetchVolumesResourceMonitorsByAgentID", s.Subtest(func(db database.Store, check *expects) { @@ -4652,6 +4652,6 @@ func (s *MethodTestSuite) TestResourcesMonitor() { monitors, err := db.FetchVolumesResourceMonitorsByAgentID(context.Background(), agt.ID) require.NoError(s.T(), err) - check.Args(agt.ID).Asserts(rbac.ResourceWorkspaceAgentResourceMonitor, policy.ActionRead).Returns(monitors) + check.Args(agt.ID).Asserts(rbac.ResourceSystem, policy.ActionRead).Returns(monitors) })) } From 0bc7632abc50184863cb5a8865a456851ed0cfa7 Mon Sep 17 00:00:00 2001 From: defelmnq Date: Tue, 11 Feb 2025 02:54:34 +0000 Subject: [PATCH 07/32] work on dbauthz --- coderd/database/modelmethods.go | 8 -------- 1 file changed, 8 deletions(-) diff --git a/coderd/database/modelmethods.go b/coderd/database/modelmethods.go index 0752ed1f2942d..63e03ccb27f40 100644 --- a/coderd/database/modelmethods.go +++ b/coderd/database/modelmethods.go @@ -327,14 +327,6 @@ func (c OAuth2ProviderAppCode) RBACObject() rbac.Object { return rbac.ResourceOauth2AppCodeToken.WithOwner(c.UserID.String()) } -func (WorkspaceAgentMemoryResourceMonitor) RBACObject() rbac.Object { - return rbac.ResourceWorkspaceAgentResourceMonitor.RBACObject() -} - -func (WorkspaceAgentVolumeResourceMonitor) RBACObject() rbac.Object { - return rbac.ResourceWorkspaceAgentResourceMonitor.RBACObject() -} - func (OAuth2ProviderAppSecret) RBACObject() rbac.Object { return rbac.ResourceOauth2AppSecret } From 3085041845d0637f3be2d8f754ad7f508eb9311e Mon Sep 17 00:00:00 2001 From: defelmnq Date: Tue, 11 Feb 2025 02:59:27 +0000 Subject: [PATCH 08/32] work on rbac --- coderd/apidoc/docs.go | 2 - coderd/apidoc/swagger.json | 2 - coderd/rbac/object_gen.go | 9 - coderd/rbac/policy/policy.go | 6 - coderd/rbac/roles_test.go | 15 - codersdk/rbacresources_gen.go | 134 ++++--- docs/reference/api/members.md | 485 ++++++++++++------------- docs/reference/api/schemas.md | 71 ++-- site/src/api/rbacresourcesGenerated.ts | 4 - site/src/api/typesGenerated.ts | 2 - 10 files changed, 341 insertions(+), 389 deletions(-) diff --git a/coderd/apidoc/docs.go b/coderd/apidoc/docs.go index 3d4ae52e993db..329951003007b 100644 --- a/coderd/apidoc/docs.go +++ b/coderd/apidoc/docs.go @@ -13475,7 +13475,6 @@ const docTemplate = `{ "template", "user", "workspace", - "workspace_agent_resource_monitor", "workspace_dormant", "workspace_proxy" ], @@ -13511,7 +13510,6 @@ const docTemplate = `{ "ResourceTemplate", "ResourceUser", "ResourceWorkspace", - "ResourceWorkspaceAgentResourceMonitor", "ResourceWorkspaceDormant", "ResourceWorkspaceProxy" ] diff --git a/coderd/apidoc/swagger.json b/coderd/apidoc/swagger.json index c431f8eca5a50..63b7146365d9f 100644 --- a/coderd/apidoc/swagger.json +++ b/coderd/apidoc/swagger.json @@ -12178,7 +12178,6 @@ "template", "user", "workspace", - "workspace_agent_resource_monitor", "workspace_dormant", "workspace_proxy" ], @@ -12214,7 +12213,6 @@ "ResourceTemplate", "ResourceUser", "ResourceWorkspace", - "ResourceWorkspaceAgentResourceMonitor", "ResourceWorkspaceDormant", "ResourceWorkspaceProxy" ] diff --git a/coderd/rbac/object_gen.go b/coderd/rbac/object_gen.go index 547e10859b5b7..42e9e16c50279 100644 --- a/coderd/rbac/object_gen.go +++ b/coderd/rbac/object_gen.go @@ -295,14 +295,6 @@ var ( Type: "workspace", } - // ResourceWorkspaceAgentResourceMonitor - // Valid Actions - // - "ActionCreate" :: create workspace agent resource monitor - // - "ActionRead" :: read workspace agent resource monitor - ResourceWorkspaceAgentResourceMonitor = Object{ - Type: "workspace_agent_resource_monitor", - } - // ResourceWorkspaceDormant // Valid Actions // - "ActionApplicationConnect" :: connect to workspace apps via browser @@ -361,7 +353,6 @@ func AllResources() []Objecter { ResourceTemplate, ResourceUser, ResourceWorkspace, - ResourceWorkspaceAgentResourceMonitor, ResourceWorkspaceDormant, ResourceWorkspaceProxy, } diff --git a/coderd/rbac/policy/policy.go b/coderd/rbac/policy/policy.go index 6dc64f6660248..e57c2eaa234f7 100644 --- a/coderd/rbac/policy/policy.go +++ b/coderd/rbac/policy/policy.go @@ -302,10 +302,4 @@ var RBACPermissions = map[string]PermissionDefinition{ ActionUpdate: actDef("update IdP sync settings"), }, }, - "workspace_agent_resource_monitor": { - Actions: map[Action]ActionDefinition{ - ActionRead: actDef("read workspace agent resource monitor"), - ActionCreate: actDef("create workspace agent resource monitor"), - }, - }, } diff --git a/coderd/rbac/roles_test.go b/coderd/rbac/roles_test.go index 6db591d028454..6d42b1b05361c 100644 --- a/coderd/rbac/roles_test.go +++ b/coderd/rbac/roles_test.go @@ -777,21 +777,6 @@ func TestRolePermissions(t *testing.T) { }, }, }, - { - Name: "ResourceMonitor", - Actions: []policy.Action{policy.ActionRead, policy.ActionCreate}, - Resource: rbac.ResourceWorkspaceAgentResourceMonitor, - AuthorizeMap: map[bool][]hasAuthSubjects{ - true: {owner}, - false: { - memberMe, orgMemberMe, otherOrgMember, - orgAdmin, otherOrgAdmin, - orgAuditor, otherOrgAuditor, - templateAdmin, orgTemplateAdmin, otherOrgTemplateAdmin, - userAdmin, orgUserAdmin, otherOrgUserAdmin, - }, - }, - }, } // We expect every permission to be tested above. diff --git a/codersdk/rbacresources_gen.go b/codersdk/rbacresources_gen.go index 8afb1858ca15c..8de32c107aae4 100644 --- a/codersdk/rbacresources_gen.go +++ b/codersdk/rbacresources_gen.go @@ -4,40 +4,39 @@ package codersdk type RBACResource string const ( - ResourceWildcard RBACResource = "*" - ResourceApiKey RBACResource = "api_key" - ResourceAssignOrgRole RBACResource = "assign_org_role" - ResourceAssignRole RBACResource = "assign_role" - ResourceAuditLog RBACResource = "audit_log" - ResourceCryptoKey RBACResource = "crypto_key" - ResourceDebugInfo RBACResource = "debug_info" - ResourceDeploymentConfig RBACResource = "deployment_config" - ResourceDeploymentStats RBACResource = "deployment_stats" - ResourceFile RBACResource = "file" - ResourceGroup RBACResource = "group" - ResourceGroupMember RBACResource = "group_member" - ResourceIdpsyncSettings RBACResource = "idpsync_settings" - ResourceLicense RBACResource = "license" - ResourceNotificationMessage RBACResource = "notification_message" - ResourceNotificationPreference RBACResource = "notification_preference" - ResourceNotificationTemplate RBACResource = "notification_template" - ResourceOauth2App RBACResource = "oauth2_app" - ResourceOauth2AppCodeToken RBACResource = "oauth2_app_code_token" - ResourceOauth2AppSecret RBACResource = "oauth2_app_secret" - ResourceOrganization RBACResource = "organization" - ResourceOrganizationMember RBACResource = "organization_member" - ResourceProvisionerDaemon RBACResource = "provisioner_daemon" - ResourceProvisionerJobs RBACResource = "provisioner_jobs" - ResourceProvisionerKeys RBACResource = "provisioner_keys" - ResourceReplicas RBACResource = "replicas" - ResourceSystem RBACResource = "system" - ResourceTailnetCoordinator RBACResource = "tailnet_coordinator" - ResourceTemplate RBACResource = "template" - ResourceUser RBACResource = "user" - ResourceWorkspace RBACResource = "workspace" - ResourceWorkspaceAgentResourceMonitor RBACResource = "workspace_agent_resource_monitor" - ResourceWorkspaceDormant RBACResource = "workspace_dormant" - ResourceWorkspaceProxy RBACResource = "workspace_proxy" + ResourceWildcard RBACResource = "*" + ResourceApiKey RBACResource = "api_key" + ResourceAssignOrgRole RBACResource = "assign_org_role" + ResourceAssignRole RBACResource = "assign_role" + ResourceAuditLog RBACResource = "audit_log" + ResourceCryptoKey RBACResource = "crypto_key" + ResourceDebugInfo RBACResource = "debug_info" + ResourceDeploymentConfig RBACResource = "deployment_config" + ResourceDeploymentStats RBACResource = "deployment_stats" + ResourceFile RBACResource = "file" + ResourceGroup RBACResource = "group" + ResourceGroupMember RBACResource = "group_member" + ResourceIdpsyncSettings RBACResource = "idpsync_settings" + ResourceLicense RBACResource = "license" + ResourceNotificationMessage RBACResource = "notification_message" + ResourceNotificationPreference RBACResource = "notification_preference" + ResourceNotificationTemplate RBACResource = "notification_template" + ResourceOauth2App RBACResource = "oauth2_app" + ResourceOauth2AppCodeToken RBACResource = "oauth2_app_code_token" + ResourceOauth2AppSecret RBACResource = "oauth2_app_secret" + ResourceOrganization RBACResource = "organization" + ResourceOrganizationMember RBACResource = "organization_member" + ResourceProvisionerDaemon RBACResource = "provisioner_daemon" + ResourceProvisionerJobs RBACResource = "provisioner_jobs" + ResourceProvisionerKeys RBACResource = "provisioner_keys" + ResourceReplicas RBACResource = "replicas" + ResourceSystem RBACResource = "system" + ResourceTailnetCoordinator RBACResource = "tailnet_coordinator" + ResourceTemplate RBACResource = "template" + ResourceUser RBACResource = "user" + ResourceWorkspace RBACResource = "workspace" + ResourceWorkspaceDormant RBACResource = "workspace_dormant" + ResourceWorkspaceProxy RBACResource = "workspace_proxy" ) type RBACAction string @@ -61,38 +60,37 @@ const ( // RBACResourceActions is the mapping of resources to which actions are valid for // said resource type. var RBACResourceActions = map[RBACResource][]RBACAction{ - ResourceWildcard: {}, - ResourceApiKey: {ActionCreate, ActionDelete, ActionRead, ActionUpdate}, - ResourceAssignOrgRole: {ActionAssign, ActionCreate, ActionDelete, ActionRead, ActionUpdate}, - ResourceAssignRole: {ActionAssign, ActionCreate, ActionDelete, ActionRead, ActionUpdate}, - ResourceAuditLog: {ActionCreate, ActionRead}, - ResourceCryptoKey: {ActionCreate, ActionDelete, ActionRead, ActionUpdate}, - ResourceDebugInfo: {ActionRead}, - ResourceDeploymentConfig: {ActionRead, ActionUpdate}, - ResourceDeploymentStats: {ActionRead}, - ResourceFile: {ActionCreate, ActionRead}, - ResourceGroup: {ActionCreate, ActionDelete, ActionRead, ActionUpdate}, - ResourceGroupMember: {ActionRead}, - ResourceIdpsyncSettings: {ActionRead, ActionUpdate}, - ResourceLicense: {ActionCreate, ActionDelete, ActionRead}, - ResourceNotificationMessage: {ActionCreate, ActionDelete, ActionRead, ActionUpdate}, - ResourceNotificationPreference: {ActionRead, ActionUpdate}, - ResourceNotificationTemplate: {ActionRead, ActionUpdate}, - ResourceOauth2App: {ActionCreate, ActionDelete, ActionRead, ActionUpdate}, - ResourceOauth2AppCodeToken: {ActionCreate, ActionDelete, ActionRead}, - ResourceOauth2AppSecret: {ActionCreate, ActionDelete, ActionRead, ActionUpdate}, - ResourceOrganization: {ActionCreate, ActionDelete, ActionRead, ActionUpdate}, - ResourceOrganizationMember: {ActionCreate, ActionDelete, ActionRead, ActionUpdate}, - ResourceProvisionerDaemon: {ActionCreate, ActionDelete, ActionRead, ActionUpdate}, - ResourceProvisionerJobs: {ActionRead}, - ResourceProvisionerKeys: {ActionCreate, ActionDelete, ActionRead}, - ResourceReplicas: {ActionRead}, - ResourceSystem: {ActionCreate, ActionDelete, ActionRead, ActionUpdate}, - ResourceTailnetCoordinator: {ActionCreate, ActionDelete, ActionRead, ActionUpdate}, - ResourceTemplate: {ActionCreate, ActionDelete, ActionRead, ActionUpdate, ActionUse, ActionViewInsights}, - ResourceUser: {ActionCreate, ActionDelete, ActionRead, ActionReadPersonal, ActionUpdate, ActionUpdatePersonal}, - ResourceWorkspace: {ActionApplicationConnect, ActionCreate, ActionDelete, ActionRead, ActionSSH, ActionWorkspaceStart, ActionWorkspaceStop, ActionUpdate}, - ResourceWorkspaceAgentResourceMonitor: {ActionCreate, ActionRead}, - ResourceWorkspaceDormant: {ActionApplicationConnect, ActionCreate, ActionDelete, ActionRead, ActionSSH, ActionWorkspaceStart, ActionWorkspaceStop, ActionUpdate}, - ResourceWorkspaceProxy: {ActionCreate, ActionDelete, ActionRead, ActionUpdate}, + ResourceWildcard: {}, + ResourceApiKey: {ActionCreate, ActionDelete, ActionRead, ActionUpdate}, + ResourceAssignOrgRole: {ActionAssign, ActionCreate, ActionDelete, ActionRead, ActionUpdate}, + ResourceAssignRole: {ActionAssign, ActionCreate, ActionDelete, ActionRead, ActionUpdate}, + ResourceAuditLog: {ActionCreate, ActionRead}, + ResourceCryptoKey: {ActionCreate, ActionDelete, ActionRead, ActionUpdate}, + ResourceDebugInfo: {ActionRead}, + ResourceDeploymentConfig: {ActionRead, ActionUpdate}, + ResourceDeploymentStats: {ActionRead}, + ResourceFile: {ActionCreate, ActionRead}, + ResourceGroup: {ActionCreate, ActionDelete, ActionRead, ActionUpdate}, + ResourceGroupMember: {ActionRead}, + ResourceIdpsyncSettings: {ActionRead, ActionUpdate}, + ResourceLicense: {ActionCreate, ActionDelete, ActionRead}, + ResourceNotificationMessage: {ActionCreate, ActionDelete, ActionRead, ActionUpdate}, + ResourceNotificationPreference: {ActionRead, ActionUpdate}, + ResourceNotificationTemplate: {ActionRead, ActionUpdate}, + ResourceOauth2App: {ActionCreate, ActionDelete, ActionRead, ActionUpdate}, + ResourceOauth2AppCodeToken: {ActionCreate, ActionDelete, ActionRead}, + ResourceOauth2AppSecret: {ActionCreate, ActionDelete, ActionRead, ActionUpdate}, + ResourceOrganization: {ActionCreate, ActionDelete, ActionRead, ActionUpdate}, + ResourceOrganizationMember: {ActionCreate, ActionDelete, ActionRead, ActionUpdate}, + ResourceProvisionerDaemon: {ActionCreate, ActionDelete, ActionRead, ActionUpdate}, + ResourceProvisionerJobs: {ActionRead}, + ResourceProvisionerKeys: {ActionCreate, ActionDelete, ActionRead}, + ResourceReplicas: {ActionRead}, + ResourceSystem: {ActionCreate, ActionDelete, ActionRead, ActionUpdate}, + ResourceTailnetCoordinator: {ActionCreate, ActionDelete, ActionRead, ActionUpdate}, + ResourceTemplate: {ActionCreate, ActionDelete, ActionRead, ActionUpdate, ActionUse, ActionViewInsights}, + ResourceUser: {ActionCreate, ActionDelete, ActionRead, ActionReadPersonal, ActionUpdate, ActionUpdatePersonal}, + ResourceWorkspace: {ActionApplicationConnect, ActionCreate, ActionDelete, ActionRead, ActionSSH, ActionWorkspaceStart, ActionWorkspaceStop, ActionUpdate}, + ResourceWorkspaceDormant: {ActionApplicationConnect, ActionCreate, ActionDelete, ActionRead, ActionSSH, ActionWorkspaceStart, ActionWorkspaceStop, ActionUpdate}, + ResourceWorkspaceProxy: {ActionCreate, ActionDelete, ActionRead, ActionUpdate}, } diff --git a/docs/reference/api/members.md b/docs/reference/api/members.md index a3a38457c6631..efe76a2eda58e 100644 --- a/docs/reference/api/members.md +++ b/docs/reference/api/members.md @@ -164,55 +164,54 @@ Status Code **200** #### Enumerated Values -| Property | Value | -|-----------------|------------------------------------| -| `action` | `application_connect` | -| `action` | `assign` | -| `action` | `create` | -| `action` | `delete` | -| `action` | `read` | -| `action` | `read_personal` | -| `action` | `ssh` | -| `action` | `update` | -| `action` | `update_personal` | -| `action` | `use` | -| `action` | `view_insights` | -| `action` | `start` | -| `action` | `stop` | -| `resource_type` | `*` | -| `resource_type` | `api_key` | -| `resource_type` | `assign_org_role` | -| `resource_type` | `assign_role` | -| `resource_type` | `audit_log` | -| `resource_type` | `crypto_key` | -| `resource_type` | `debug_info` | -| `resource_type` | `deployment_config` | -| `resource_type` | `deployment_stats` | -| `resource_type` | `file` | -| `resource_type` | `group` | -| `resource_type` | `group_member` | -| `resource_type` | `idpsync_settings` | -| `resource_type` | `license` | -| `resource_type` | `notification_message` | -| `resource_type` | `notification_preference` | -| `resource_type` | `notification_template` | -| `resource_type` | `oauth2_app` | -| `resource_type` | `oauth2_app_code_token` | -| `resource_type` | `oauth2_app_secret` | -| `resource_type` | `organization` | -| `resource_type` | `organization_member` | -| `resource_type` | `provisioner_daemon` | -| `resource_type` | `provisioner_jobs` | -| `resource_type` | `provisioner_keys` | -| `resource_type` | `replicas` | -| `resource_type` | `system` | -| `resource_type` | `tailnet_coordinator` | -| `resource_type` | `template` | -| `resource_type` | `user` | -| `resource_type` | `workspace` | -| `resource_type` | `workspace_agent_resource_monitor` | -| `resource_type` | `workspace_dormant` | -| `resource_type` | `workspace_proxy` | +| Property | Value | +|-----------------|---------------------------| +| `action` | `application_connect` | +| `action` | `assign` | +| `action` | `create` | +| `action` | `delete` | +| `action` | `read` | +| `action` | `read_personal` | +| `action` | `ssh` | +| `action` | `update` | +| `action` | `update_personal` | +| `action` | `use` | +| `action` | `view_insights` | +| `action` | `start` | +| `action` | `stop` | +| `resource_type` | `*` | +| `resource_type` | `api_key` | +| `resource_type` | `assign_org_role` | +| `resource_type` | `assign_role` | +| `resource_type` | `audit_log` | +| `resource_type` | `crypto_key` | +| `resource_type` | `debug_info` | +| `resource_type` | `deployment_config` | +| `resource_type` | `deployment_stats` | +| `resource_type` | `file` | +| `resource_type` | `group` | +| `resource_type` | `group_member` | +| `resource_type` | `idpsync_settings` | +| `resource_type` | `license` | +| `resource_type` | `notification_message` | +| `resource_type` | `notification_preference` | +| `resource_type` | `notification_template` | +| `resource_type` | `oauth2_app` | +| `resource_type` | `oauth2_app_code_token` | +| `resource_type` | `oauth2_app_secret` | +| `resource_type` | `organization` | +| `resource_type` | `organization_member` | +| `resource_type` | `provisioner_daemon` | +| `resource_type` | `provisioner_jobs` | +| `resource_type` | `provisioner_keys` | +| `resource_type` | `replicas` | +| `resource_type` | `system` | +| `resource_type` | `tailnet_coordinator` | +| `resource_type` | `template` | +| `resource_type` | `user` | +| `resource_type` | `workspace` | +| `resource_type` | `workspace_dormant` | +| `resource_type` | `workspace_proxy` | To perform this operation, you must be authenticated. [Learn more](authentication.md). @@ -327,55 +326,54 @@ Status Code **200** #### Enumerated Values -| Property | Value | -|-----------------|------------------------------------| -| `action` | `application_connect` | -| `action` | `assign` | -| `action` | `create` | -| `action` | `delete` | -| `action` | `read` | -| `action` | `read_personal` | -| `action` | `ssh` | -| `action` | `update` | -| `action` | `update_personal` | -| `action` | `use` | -| `action` | `view_insights` | -| `action` | `start` | -| `action` | `stop` | -| `resource_type` | `*` | -| `resource_type` | `api_key` | -| `resource_type` | `assign_org_role` | -| `resource_type` | `assign_role` | -| `resource_type` | `audit_log` | -| `resource_type` | `crypto_key` | -| `resource_type` | `debug_info` | -| `resource_type` | `deployment_config` | -| `resource_type` | `deployment_stats` | -| `resource_type` | `file` | -| `resource_type` | `group` | -| `resource_type` | `group_member` | -| `resource_type` | `idpsync_settings` | -| `resource_type` | `license` | -| `resource_type` | `notification_message` | -| `resource_type` | `notification_preference` | -| `resource_type` | `notification_template` | -| `resource_type` | `oauth2_app` | -| `resource_type` | `oauth2_app_code_token` | -| `resource_type` | `oauth2_app_secret` | -| `resource_type` | `organization` | -| `resource_type` | `organization_member` | -| `resource_type` | `provisioner_daemon` | -| `resource_type` | `provisioner_jobs` | -| `resource_type` | `provisioner_keys` | -| `resource_type` | `replicas` | -| `resource_type` | `system` | -| `resource_type` | `tailnet_coordinator` | -| `resource_type` | `template` | -| `resource_type` | `user` | -| `resource_type` | `workspace` | -| `resource_type` | `workspace_agent_resource_monitor` | -| `resource_type` | `workspace_dormant` | -| `resource_type` | `workspace_proxy` | +| Property | Value | +|-----------------|---------------------------| +| `action` | `application_connect` | +| `action` | `assign` | +| `action` | `create` | +| `action` | `delete` | +| `action` | `read` | +| `action` | `read_personal` | +| `action` | `ssh` | +| `action` | `update` | +| `action` | `update_personal` | +| `action` | `use` | +| `action` | `view_insights` | +| `action` | `start` | +| `action` | `stop` | +| `resource_type` | `*` | +| `resource_type` | `api_key` | +| `resource_type` | `assign_org_role` | +| `resource_type` | `assign_role` | +| `resource_type` | `audit_log` | +| `resource_type` | `crypto_key` | +| `resource_type` | `debug_info` | +| `resource_type` | `deployment_config` | +| `resource_type` | `deployment_stats` | +| `resource_type` | `file` | +| `resource_type` | `group` | +| `resource_type` | `group_member` | +| `resource_type` | `idpsync_settings` | +| `resource_type` | `license` | +| `resource_type` | `notification_message` | +| `resource_type` | `notification_preference` | +| `resource_type` | `notification_template` | +| `resource_type` | `oauth2_app` | +| `resource_type` | `oauth2_app_code_token` | +| `resource_type` | `oauth2_app_secret` | +| `resource_type` | `organization` | +| `resource_type` | `organization_member` | +| `resource_type` | `provisioner_daemon` | +| `resource_type` | `provisioner_jobs` | +| `resource_type` | `provisioner_keys` | +| `resource_type` | `replicas` | +| `resource_type` | `system` | +| `resource_type` | `tailnet_coordinator` | +| `resource_type` | `template` | +| `resource_type` | `user` | +| `resource_type` | `workspace` | +| `resource_type` | `workspace_dormant` | +| `resource_type` | `workspace_proxy` | To perform this operation, you must be authenticated. [Learn more](authentication.md). @@ -490,55 +488,54 @@ Status Code **200** #### Enumerated Values -| Property | Value | -|-----------------|------------------------------------| -| `action` | `application_connect` | -| `action` | `assign` | -| `action` | `create` | -| `action` | `delete` | -| `action` | `read` | -| `action` | `read_personal` | -| `action` | `ssh` | -| `action` | `update` | -| `action` | `update_personal` | -| `action` | `use` | -| `action` | `view_insights` | -| `action` | `start` | -| `action` | `stop` | -| `resource_type` | `*` | -| `resource_type` | `api_key` | -| `resource_type` | `assign_org_role` | -| `resource_type` | `assign_role` | -| `resource_type` | `audit_log` | -| `resource_type` | `crypto_key` | -| `resource_type` | `debug_info` | -| `resource_type` | `deployment_config` | -| `resource_type` | `deployment_stats` | -| `resource_type` | `file` | -| `resource_type` | `group` | -| `resource_type` | `group_member` | -| `resource_type` | `idpsync_settings` | -| `resource_type` | `license` | -| `resource_type` | `notification_message` | -| `resource_type` | `notification_preference` | -| `resource_type` | `notification_template` | -| `resource_type` | `oauth2_app` | -| `resource_type` | `oauth2_app_code_token` | -| `resource_type` | `oauth2_app_secret` | -| `resource_type` | `organization` | -| `resource_type` | `organization_member` | -| `resource_type` | `provisioner_daemon` | -| `resource_type` | `provisioner_jobs` | -| `resource_type` | `provisioner_keys` | -| `resource_type` | `replicas` | -| `resource_type` | `system` | -| `resource_type` | `tailnet_coordinator` | -| `resource_type` | `template` | -| `resource_type` | `user` | -| `resource_type` | `workspace` | -| `resource_type` | `workspace_agent_resource_monitor` | -| `resource_type` | `workspace_dormant` | -| `resource_type` | `workspace_proxy` | +| Property | Value | +|-----------------|---------------------------| +| `action` | `application_connect` | +| `action` | `assign` | +| `action` | `create` | +| `action` | `delete` | +| `action` | `read` | +| `action` | `read_personal` | +| `action` | `ssh` | +| `action` | `update` | +| `action` | `update_personal` | +| `action` | `use` | +| `action` | `view_insights` | +| `action` | `start` | +| `action` | `stop` | +| `resource_type` | `*` | +| `resource_type` | `api_key` | +| `resource_type` | `assign_org_role` | +| `resource_type` | `assign_role` | +| `resource_type` | `audit_log` | +| `resource_type` | `crypto_key` | +| `resource_type` | `debug_info` | +| `resource_type` | `deployment_config` | +| `resource_type` | `deployment_stats` | +| `resource_type` | `file` | +| `resource_type` | `group` | +| `resource_type` | `group_member` | +| `resource_type` | `idpsync_settings` | +| `resource_type` | `license` | +| `resource_type` | `notification_message` | +| `resource_type` | `notification_preference` | +| `resource_type` | `notification_template` | +| `resource_type` | `oauth2_app` | +| `resource_type` | `oauth2_app_code_token` | +| `resource_type` | `oauth2_app_secret` | +| `resource_type` | `organization` | +| `resource_type` | `organization_member` | +| `resource_type` | `provisioner_daemon` | +| `resource_type` | `provisioner_jobs` | +| `resource_type` | `provisioner_keys` | +| `resource_type` | `replicas` | +| `resource_type` | `system` | +| `resource_type` | `tailnet_coordinator` | +| `resource_type` | `template` | +| `resource_type` | `user` | +| `resource_type` | `workspace` | +| `resource_type` | `workspace_dormant` | +| `resource_type` | `workspace_proxy` | To perform this operation, you must be authenticated. [Learn more](authentication.md). @@ -622,55 +619,54 @@ Status Code **200** #### Enumerated Values -| Property | Value | -|-----------------|------------------------------------| -| `action` | `application_connect` | -| `action` | `assign` | -| `action` | `create` | -| `action` | `delete` | -| `action` | `read` | -| `action` | `read_personal` | -| `action` | `ssh` | -| `action` | `update` | -| `action` | `update_personal` | -| `action` | `use` | -| `action` | `view_insights` | -| `action` | `start` | -| `action` | `stop` | -| `resource_type` | `*` | -| `resource_type` | `api_key` | -| `resource_type` | `assign_org_role` | -| `resource_type` | `assign_role` | -| `resource_type` | `audit_log` | -| `resource_type` | `crypto_key` | -| `resource_type` | `debug_info` | -| `resource_type` | `deployment_config` | -| `resource_type` | `deployment_stats` | -| `resource_type` | `file` | -| `resource_type` | `group` | -| `resource_type` | `group_member` | -| `resource_type` | `idpsync_settings` | -| `resource_type` | `license` | -| `resource_type` | `notification_message` | -| `resource_type` | `notification_preference` | -| `resource_type` | `notification_template` | -| `resource_type` | `oauth2_app` | -| `resource_type` | `oauth2_app_code_token` | -| `resource_type` | `oauth2_app_secret` | -| `resource_type` | `organization` | -| `resource_type` | `organization_member` | -| `resource_type` | `provisioner_daemon` | -| `resource_type` | `provisioner_jobs` | -| `resource_type` | `provisioner_keys` | -| `resource_type` | `replicas` | -| `resource_type` | `system` | -| `resource_type` | `tailnet_coordinator` | -| `resource_type` | `template` | -| `resource_type` | `user` | -| `resource_type` | `workspace` | -| `resource_type` | `workspace_agent_resource_monitor` | -| `resource_type` | `workspace_dormant` | -| `resource_type` | `workspace_proxy` | +| Property | Value | +|-----------------|---------------------------| +| `action` | `application_connect` | +| `action` | `assign` | +| `action` | `create` | +| `action` | `delete` | +| `action` | `read` | +| `action` | `read_personal` | +| `action` | `ssh` | +| `action` | `update` | +| `action` | `update_personal` | +| `action` | `use` | +| `action` | `view_insights` | +| `action` | `start` | +| `action` | `stop` | +| `resource_type` | `*` | +| `resource_type` | `api_key` | +| `resource_type` | `assign_org_role` | +| `resource_type` | `assign_role` | +| `resource_type` | `audit_log` | +| `resource_type` | `crypto_key` | +| `resource_type` | `debug_info` | +| `resource_type` | `deployment_config` | +| `resource_type` | `deployment_stats` | +| `resource_type` | `file` | +| `resource_type` | `group` | +| `resource_type` | `group_member` | +| `resource_type` | `idpsync_settings` | +| `resource_type` | `license` | +| `resource_type` | `notification_message` | +| `resource_type` | `notification_preference` | +| `resource_type` | `notification_template` | +| `resource_type` | `oauth2_app` | +| `resource_type` | `oauth2_app_code_token` | +| `resource_type` | `oauth2_app_secret` | +| `resource_type` | `organization` | +| `resource_type` | `organization_member` | +| `resource_type` | `provisioner_daemon` | +| `resource_type` | `provisioner_jobs` | +| `resource_type` | `provisioner_keys` | +| `resource_type` | `replicas` | +| `resource_type` | `system` | +| `resource_type` | `tailnet_coordinator` | +| `resource_type` | `template` | +| `resource_type` | `user` | +| `resource_type` | `workspace` | +| `resource_type` | `workspace_dormant` | +| `resource_type` | `workspace_proxy` | To perform this operation, you must be authenticated. [Learn more](authentication.md). @@ -886,54 +882,53 @@ Status Code **200** #### Enumerated Values -| Property | Value | -|-----------------|------------------------------------| -| `action` | `application_connect` | -| `action` | `assign` | -| `action` | `create` | -| `action` | `delete` | -| `action` | `read` | -| `action` | `read_personal` | -| `action` | `ssh` | -| `action` | `update` | -| `action` | `update_personal` | -| `action` | `use` | -| `action` | `view_insights` | -| `action` | `start` | -| `action` | `stop` | -| `resource_type` | `*` | -| `resource_type` | `api_key` | -| `resource_type` | `assign_org_role` | -| `resource_type` | `assign_role` | -| `resource_type` | `audit_log` | -| `resource_type` | `crypto_key` | -| `resource_type` | `debug_info` | -| `resource_type` | `deployment_config` | -| `resource_type` | `deployment_stats` | -| `resource_type` | `file` | -| `resource_type` | `group` | -| `resource_type` | `group_member` | -| `resource_type` | `idpsync_settings` | -| `resource_type` | `license` | -| `resource_type` | `notification_message` | -| `resource_type` | `notification_preference` | -| `resource_type` | `notification_template` | -| `resource_type` | `oauth2_app` | -| `resource_type` | `oauth2_app_code_token` | -| `resource_type` | `oauth2_app_secret` | -| `resource_type` | `organization` | -| `resource_type` | `organization_member` | -| `resource_type` | `provisioner_daemon` | -| `resource_type` | `provisioner_jobs` | -| `resource_type` | `provisioner_keys` | -| `resource_type` | `replicas` | -| `resource_type` | `system` | -| `resource_type` | `tailnet_coordinator` | -| `resource_type` | `template` | -| `resource_type` | `user` | -| `resource_type` | `workspace` | -| `resource_type` | `workspace_agent_resource_monitor` | -| `resource_type` | `workspace_dormant` | -| `resource_type` | `workspace_proxy` | +| Property | Value | +|-----------------|---------------------------| +| `action` | `application_connect` | +| `action` | `assign` | +| `action` | `create` | +| `action` | `delete` | +| `action` | `read` | +| `action` | `read_personal` | +| `action` | `ssh` | +| `action` | `update` | +| `action` | `update_personal` | +| `action` | `use` | +| `action` | `view_insights` | +| `action` | `start` | +| `action` | `stop` | +| `resource_type` | `*` | +| `resource_type` | `api_key` | +| `resource_type` | `assign_org_role` | +| `resource_type` | `assign_role` | +| `resource_type` | `audit_log` | +| `resource_type` | `crypto_key` | +| `resource_type` | `debug_info` | +| `resource_type` | `deployment_config` | +| `resource_type` | `deployment_stats` | +| `resource_type` | `file` | +| `resource_type` | `group` | +| `resource_type` | `group_member` | +| `resource_type` | `idpsync_settings` | +| `resource_type` | `license` | +| `resource_type` | `notification_message` | +| `resource_type` | `notification_preference` | +| `resource_type` | `notification_template` | +| `resource_type` | `oauth2_app` | +| `resource_type` | `oauth2_app_code_token` | +| `resource_type` | `oauth2_app_secret` | +| `resource_type` | `organization` | +| `resource_type` | `organization_member` | +| `resource_type` | `provisioner_daemon` | +| `resource_type` | `provisioner_jobs` | +| `resource_type` | `provisioner_keys` | +| `resource_type` | `replicas` | +| `resource_type` | `system` | +| `resource_type` | `tailnet_coordinator` | +| `resource_type` | `template` | +| `resource_type` | `user` | +| `resource_type` | `workspace` | +| `resource_type` | `workspace_dormant` | +| `resource_type` | `workspace_proxy` | To perform this operation, you must be authenticated. [Learn more](authentication.md). diff --git a/docs/reference/api/schemas.md b/docs/reference/api/schemas.md index 1af6ac7285d04..20ed37f81f7f7 100644 --- a/docs/reference/api/schemas.md +++ b/docs/reference/api/schemas.md @@ -4991,42 +4991,41 @@ Git clone makes use of this by parsing the URL from: 'Username for "https://gith #### Enumerated Values -| Value | -|------------------------------------| -| `*` | -| `api_key` | -| `assign_org_role` | -| `assign_role` | -| `audit_log` | -| `crypto_key` | -| `debug_info` | -| `deployment_config` | -| `deployment_stats` | -| `file` | -| `group` | -| `group_member` | -| `idpsync_settings` | -| `license` | -| `notification_message` | -| `notification_preference` | -| `notification_template` | -| `oauth2_app` | -| `oauth2_app_code_token` | -| `oauth2_app_secret` | -| `organization` | -| `organization_member` | -| `provisioner_daemon` | -| `provisioner_jobs` | -| `provisioner_keys` | -| `replicas` | -| `system` | -| `tailnet_coordinator` | -| `template` | -| `user` | -| `workspace` | -| `workspace_agent_resource_monitor` | -| `workspace_dormant` | -| `workspace_proxy` | +| Value | +|---------------------------| +| `*` | +| `api_key` | +| `assign_org_role` | +| `assign_role` | +| `audit_log` | +| `crypto_key` | +| `debug_info` | +| `deployment_config` | +| `deployment_stats` | +| `file` | +| `group` | +| `group_member` | +| `idpsync_settings` | +| `license` | +| `notification_message` | +| `notification_preference` | +| `notification_template` | +| `oauth2_app` | +| `oauth2_app_code_token` | +| `oauth2_app_secret` | +| `organization` | +| `organization_member` | +| `provisioner_daemon` | +| `provisioner_jobs` | +| `provisioner_keys` | +| `replicas` | +| `system` | +| `tailnet_coordinator` | +| `template` | +| `user` | +| `workspace` | +| `workspace_dormant` | +| `workspace_proxy` | ## codersdk.RateLimitConfig diff --git a/site/src/api/rbacresourcesGenerated.ts b/site/src/api/rbacresourcesGenerated.ts index e557ceddbdda6..886f1b0239694 100644 --- a/site/src/api/rbacresourcesGenerated.ts +++ b/site/src/api/rbacresourcesGenerated.ts @@ -168,10 +168,6 @@ export const RBACResourceActions: Partial< stop: "allows stopping a workspace", update: "edit workspace settings (scheduling, permissions, parameters)", }, - workspace_agent_resource_monitor: { - create: "create workspace agent resource monitor", - read: "read workspace agent resource monitor", - }, workspace_dormant: { application_connect: "connect to workspace apps via browser", create: "create a new workspace", diff --git a/site/src/api/typesGenerated.ts b/site/src/api/typesGenerated.ts index 58375a98370a0..de879ee23daa5 100644 --- a/site/src/api/typesGenerated.ts +++ b/site/src/api/typesGenerated.ts @@ -1848,7 +1848,6 @@ export type RBACResource = | "user" | "*" | "workspace" - | "workspace_agent_resource_monitor" | "workspace_dormant" | "workspace_proxy"; @@ -1884,7 +1883,6 @@ export const RBACResources: RBACResource[] = [ "user", "*", "workspace", - "workspace_agent_resource_monitor", "workspace_dormant", "workspace_proxy", ]; From 120a37b740f0448a358bcbf0d18f23207ba329b2 Mon Sep 17 00:00:00 2001 From: defelmnq Date: Tue, 11 Feb 2025 03:10:02 +0000 Subject: [PATCH 09/32] continue to iterate --- coderd/database/dbauthz/dbauthz.go | 8 -------- 1 file changed, 8 deletions(-) diff --git a/coderd/database/dbauthz/dbauthz.go b/coderd/database/dbauthz/dbauthz.go index d32ec23e9e7ef..3f40224875af7 100644 --- a/coderd/database/dbauthz/dbauthz.go +++ b/coderd/database/dbauthz/dbauthz.go @@ -1392,10 +1392,6 @@ func (q *querier) FavoriteWorkspace(ctx context.Context, id uuid.UUID) error { } func (q *querier) FetchMemoryResourceMonitorsByAgentID(ctx context.Context, agentID uuid.UUID) (database.WorkspaceAgentMemoryResourceMonitor, error) { - if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceSystem); err != nil { - return database.WorkspaceAgentMemoryResourceMonitor{}, err - } - return q.db.FetchMemoryResourceMonitorsByAgentID(ctx, agentID) } @@ -1407,10 +1403,6 @@ func (q *querier) FetchNewMessageMetadata(ctx context.Context, arg database.Fetc } func (q *querier) FetchVolumesResourceMonitorsByAgentID(ctx context.Context, agentID uuid.UUID) ([]database.WorkspaceAgentVolumeResourceMonitor, error) { - if err := q.authorizeContext(ctx, policy.ActionRead, rbac.ResourceSystem); err != nil { - return nil, err - } - return q.db.FetchVolumesResourceMonitorsByAgentID(ctx, agentID) } From dd8ed40f4119e25434ec3596097dd9b505f28cd5 Mon Sep 17 00:00:00 2001 From: defelmnq Date: Tue, 11 Feb 2025 03:11:41 +0000 Subject: [PATCH 10/32] continue to iterate --- coderd/database/dbauthz/dbauthz_test.go | 81 ------------------------- 1 file changed, 81 deletions(-) diff --git a/coderd/database/dbauthz/dbauthz_test.go b/coderd/database/dbauthz/dbauthz_test.go index cdcae62d505c6..a39c4e1874a66 100644 --- a/coderd/database/dbauthz/dbauthz_test.go +++ b/coderd/database/dbauthz/dbauthz_test.go @@ -4573,85 +4573,4 @@ func (s *MethodTestSuite) TestResourcesMonitor() { dbtestutil.DisableForeignKeysAndTriggers(s.T(), db) check.Args(database.InsertVolumeResourceMonitorParams{}).Asserts(rbac.ResourceSystem, policy.ActionCreate) })) - - s.Run("FetchMemoryResourceMonitorsByAgentID", s.Subtest(func(db database.Store, check *expects) { - u := dbgen.User(s.T(), db, database.User{}) - o := dbgen.Organization(s.T(), db, database.Organization{}) - tpl := dbgen.Template(s.T(), db, database.Template{ - OrganizationID: o.ID, - CreatedBy: u.ID, - }) - tv := dbgen.TemplateVersion(s.T(), db, database.TemplateVersion{ - TemplateID: uuid.NullUUID{UUID: tpl.ID, Valid: true}, - OrganizationID: o.ID, - CreatedBy: u.ID, - }) - w := dbgen.Workspace(s.T(), db, database.WorkspaceTable{ - TemplateID: tpl.ID, - OrganizationID: o.ID, - OwnerID: u.ID, - }) - j := dbgen.ProvisionerJob(s.T(), db, nil, database.ProvisionerJob{ - Type: database.ProvisionerJobTypeWorkspaceBuild, - }) - b := dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{ - JobID: j.ID, - WorkspaceID: w.ID, - TemplateVersionID: tv.ID, - }) - res := dbgen.WorkspaceResource(s.T(), db, database.WorkspaceResource{JobID: b.JobID}) - agt := dbgen.WorkspaceAgent(s.T(), db, database.WorkspaceAgent{ResourceID: res.ID}) - dbgen.WorkspaceAgentMemoryResourceMonitor(s.T(), db, database.WorkspaceAgentMemoryResourceMonitor{ - AgentID: agt.ID, - Enabled: true, - Threshold: 80, - CreatedAt: dbtime.Now(), - }) - - monitor, err := db.FetchMemoryResourceMonitorsByAgentID(context.Background(), agt.ID) - require.NoError(s.T(), err) - - check.Args(agt.ID).Asserts(rbac.ResourceSystem, policy.ActionRead).Returns(monitor) - })) - - s.Run("FetchVolumesResourceMonitorsByAgentID", s.Subtest(func(db database.Store, check *expects) { - u := dbgen.User(s.T(), db, database.User{}) - o := dbgen.Organization(s.T(), db, database.Organization{}) - tpl := dbgen.Template(s.T(), db, database.Template{ - OrganizationID: o.ID, - CreatedBy: u.ID, - }) - tv := dbgen.TemplateVersion(s.T(), db, database.TemplateVersion{ - TemplateID: uuid.NullUUID{UUID: tpl.ID, Valid: true}, - OrganizationID: o.ID, - CreatedBy: u.ID, - }) - w := dbgen.Workspace(s.T(), db, database.WorkspaceTable{ - TemplateID: tpl.ID, - OrganizationID: o.ID, - OwnerID: u.ID, - }) - j := dbgen.ProvisionerJob(s.T(), db, nil, database.ProvisionerJob{ - Type: database.ProvisionerJobTypeWorkspaceBuild, - }) - b := dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{ - JobID: j.ID, - WorkspaceID: w.ID, - TemplateVersionID: tv.ID, - }) - res := dbgen.WorkspaceResource(s.T(), db, database.WorkspaceResource{JobID: b.JobID}) - agt := dbgen.WorkspaceAgent(s.T(), db, database.WorkspaceAgent{ResourceID: res.ID}) - dbgen.WorkspaceAgentVolumeResourceMonitor(s.T(), db, database.WorkspaceAgentVolumeResourceMonitor{ - AgentID: agt.ID, - Path: "/var/lib", - Enabled: true, - Threshold: 80, - CreatedAt: dbtime.Now(), - }) - - monitors, err := db.FetchVolumesResourceMonitorsByAgentID(context.Background(), agt.ID) - require.NoError(s.T(), err) - - check.Args(agt.ID).Asserts(rbac.ResourceSystem, policy.ActionRead).Returns(monitors) - })) } From 0a8941b077acbb2ca6d390dc0c6536ae5989467d Mon Sep 17 00:00:00 2001 From: defelmnq Date: Tue, 11 Feb 2025 03:24:21 +0000 Subject: [PATCH 11/32] continue to iterate --- coderd/database/dbauthz/dbauthz_test.go | 81 +++++++++++++++++++++++++ 1 file changed, 81 insertions(+) diff --git a/coderd/database/dbauthz/dbauthz_test.go b/coderd/database/dbauthz/dbauthz_test.go index a39c4e1874a66..1506fdb5b6526 100644 --- a/coderd/database/dbauthz/dbauthz_test.go +++ b/coderd/database/dbauthz/dbauthz_test.go @@ -4573,4 +4573,85 @@ func (s *MethodTestSuite) TestResourcesMonitor() { dbtestutil.DisableForeignKeysAndTriggers(s.T(), db) check.Args(database.InsertVolumeResourceMonitorParams{}).Asserts(rbac.ResourceSystem, policy.ActionCreate) })) + + s.Run("FetchMemoryResourceMonitorsByAgentID", s.Subtest(func(db database.Store, check *expects) { + u := dbgen.User(s.T(), db, database.User{}) + o := dbgen.Organization(s.T(), db, database.Organization{}) + tpl := dbgen.Template(s.T(), db, database.Template{ + OrganizationID: o.ID, + CreatedBy: u.ID, + }) + tv := dbgen.TemplateVersion(s.T(), db, database.TemplateVersion{ + TemplateID: uuid.NullUUID{UUID: tpl.ID, Valid: true}, + OrganizationID: o.ID, + CreatedBy: u.ID, + }) + w := dbgen.Workspace(s.T(), db, database.WorkspaceTable{ + TemplateID: tpl.ID, + OrganizationID: o.ID, + OwnerID: u.ID, + }) + j := dbgen.ProvisionerJob(s.T(), db, nil, database.ProvisionerJob{ + Type: database.ProvisionerJobTypeWorkspaceBuild, + }) + b := dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{ + JobID: j.ID, + WorkspaceID: w.ID, + TemplateVersionID: tv.ID, + }) + res := dbgen.WorkspaceResource(s.T(), db, database.WorkspaceResource{JobID: b.JobID}) + agt := dbgen.WorkspaceAgent(s.T(), db, database.WorkspaceAgent{ResourceID: res.ID}) + dbgen.WorkspaceAgentMemoryResourceMonitor(s.T(), db, database.WorkspaceAgentMemoryResourceMonitor{ + AgentID: agt.ID, + Enabled: true, + Threshold: 80, + CreatedAt: dbtime.Now(), + }) + + monitor, err := db.FetchMemoryResourceMonitorsByAgentID(context.Background(), agt.ID) + require.NoError(s.T(), err) + + check.Args(agt.ID).Asserts().Returns(monitor) + })) + + s.Run("FetchVolumesResourceMonitorsByAgentID", s.Subtest(func(db database.Store, check *expects) { + u := dbgen.User(s.T(), db, database.User{}) + o := dbgen.Organization(s.T(), db, database.Organization{}) + tpl := dbgen.Template(s.T(), db, database.Template{ + OrganizationID: o.ID, + CreatedBy: u.ID, + }) + tv := dbgen.TemplateVersion(s.T(), db, database.TemplateVersion{ + TemplateID: uuid.NullUUID{UUID: tpl.ID, Valid: true}, + OrganizationID: o.ID, + CreatedBy: u.ID, + }) + w := dbgen.Workspace(s.T(), db, database.WorkspaceTable{ + TemplateID: tpl.ID, + OrganizationID: o.ID, + OwnerID: u.ID, + }) + j := dbgen.ProvisionerJob(s.T(), db, nil, database.ProvisionerJob{ + Type: database.ProvisionerJobTypeWorkspaceBuild, + }) + b := dbgen.WorkspaceBuild(s.T(), db, database.WorkspaceBuild{ + JobID: j.ID, + WorkspaceID: w.ID, + TemplateVersionID: tv.ID, + }) + res := dbgen.WorkspaceResource(s.T(), db, database.WorkspaceResource{JobID: b.JobID}) + agt := dbgen.WorkspaceAgent(s.T(), db, database.WorkspaceAgent{ResourceID: res.ID}) + dbgen.WorkspaceAgentVolumeResourceMonitor(s.T(), db, database.WorkspaceAgentVolumeResourceMonitor{ + AgentID: agt.ID, + Path: "/var/lib", + Enabled: true, + Threshold: 80, + CreatedAt: dbtime.Now(), + }) + + monitors, err := db.FetchVolumesResourceMonitorsByAgentID(context.Background(), agt.ID) + require.NoError(s.T(), err) + + check.Args(agt.ID).Asserts().Returns(monitors) + })) } From f3388b4f2db5160667eaaa4017327253df671c7e Mon Sep 17 00:00:00 2001 From: defelmnq Date: Tue, 11 Feb 2025 03:46:06 +0000 Subject: [PATCH 12/32] work on tests --- agent/agenttest/client.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/agent/agenttest/client.go b/agent/agenttest/client.go index c530c8e6a79e9..4edbc23c571e0 100644 --- a/agent/agenttest/client.go +++ b/agent/agenttest/client.go @@ -219,7 +219,7 @@ func (f *FakeAgentAPI) GetResourcesMonitoringConfiguration(_ context.Context, _ defer f.Unlock() if f.getResourcesMonitoringConfigurationFunc == nil { - return nil, xerrors.Errorf("GetResourcesMonitoringConfiguration is not implemented") + return &agentproto.GetResourcesMonitoringConfigurationResponse{}, nil } return f.getResourcesMonitoringConfigurationFunc() @@ -230,7 +230,7 @@ func (f *FakeAgentAPI) PushResourcesMonitoringUsage(_ context.Context, req *agen defer f.Unlock() if f.pushResourcesMonitoringUsageFunc == nil { - return nil, xerrors.Errorf("PushResourcesMonitoringUsage is not implemented") + return &agentproto.PushResourcesMonitoringUsageResponse{}, nil } return f.pushResourcesMonitoringUsageFunc(req) From 523f6fd4474fb5dab2cad287ad2b71249203cef0 Mon Sep 17 00:00:00 2001 From: defelmnq Date: Tue, 11 Feb 2025 04:34:11 +0000 Subject: [PATCH 13/32] improve testing --- agent/resources_monitor_test.go | 88 ++++++++++++++++----------------- 1 file changed, 42 insertions(+), 46 deletions(-) diff --git a/agent/resources_monitor_test.go b/agent/resources_monitor_test.go index 45d7a886b2867..6f819c99435fe 100644 --- a/agent/resources_monitor_test.go +++ b/agent/resources_monitor_test.go @@ -5,6 +5,8 @@ import ( "os" "testing" + "golang.org/x/xerrors" + "cdr.dev/slog" "cdr.dev/slog/sloggers/sloghuman" "github.com/coder/coder/v2/agent" @@ -25,8 +27,8 @@ func TestPushResourcesMonitoringWithConfig(t *testing.T) { expectedCalls int }{ { - name: "Successful monitoring", - configFetcher: func(_ context.Context, params *proto.GetResourcesMonitoringConfigurationRequest) (*proto.GetResourcesMonitoringConfigurationResponse, error) { + name: "SuccessfulMonitoring", + configFetcher: func(_ context.Context, _ *proto.GetResourcesMonitoringConfigurationRequest) (*proto.GetResourcesMonitoringConfigurationResponse, error) { return &proto.GetResourcesMonitoringConfigurationResponse{ Enabled: true, Config: &proto.GetResourcesMonitoringConfigurationResponse_Config{ @@ -36,7 +38,7 @@ func TestPushResourcesMonitoringWithConfig(t *testing.T) { MonitoredVolumes: []string{"/"}, }, nil }, - datapointsPusher: func(_ context.Context, params *proto.PushResourcesMonitoringUsageRequest) (*proto.PushResourcesMonitoringUsageResponse, error) { + datapointsPusher: func(_ context.Context, _ *proto.PushResourcesMonitoringUsageRequest) (*proto.PushResourcesMonitoringUsageResponse, error) { return &proto.PushResourcesMonitoringUsageResponse{}, nil }, expectedError: false, @@ -44,48 +46,39 @@ func TestPushResourcesMonitoringWithConfig(t *testing.T) { counterCalls: 0, expectedCalls: 1, }, - // { - // name: "Disabled monitoring", - // configFetcher: func(ctx context.Context, params *proto.GetResourcesMonitoringConfigurationRequest) (*proto.GetResourcesMonitoringConfigurationResponse, error) { - // return &proto.GetResourcesMonitoringConfigurationResponse{ - // Enabled: false, - // }, nil - // }, - // datapointsPusher: func(ctx context.Context, params *proto.PushResourcesMonitoringUsageRequest) (*proto.PushResourcesMonitoringUsageResponse, error) { - // return &proto.PushResourcesMonitoringUsageResponse{}, nil - // }, - // expectedError: false, - // expectedCalls: 0, - // }, - // { - // name: "Failed to fetch configuration", - // configFetcher: func(ctx context.Context, params *proto.GetResourcesMonitoringConfigurationRequest) (*proto.GetResourcesMonitoringConfigurationResponse, error) { - // return nil, xerrors.New("failed to fetch configuration") - // }, - // datapointsPusher: func(ctx context.Context, params *proto.PushResourcesMonitoringUsageRequest) (*proto.PushResourcesMonitoringUsageResponse, error) { - // return &proto.PushResourcesMonitoringUsageResponse{}, nil - // }, - // expectedError: true, - // expectedCalls: 0, - // }, - // { - // name: "Failed to push datapoints", - // configFetcher: func(ctx context.Context, params *proto.GetResourcesMonitoringConfigurationRequest) (*proto.GetResourcesMonitoringConfigurationResponse, error) { - // return &proto.GetResourcesMonitoringConfigurationResponse{ - // Enabled: true, - // Config: &proto.GetResourcesMonitoringConfigurationResponse_Config{ - // NumDatapoints: 1, - // TickInterval: 1, - // }, - // MonitoredVolumes: []string{"/"}, - // }, nil - // }, - // datapointsPusher: func(ctx context.Context, params *proto.PushResourcesMonitoringUsageRequest) (*proto.PushResourcesMonitoringUsageResponse, error) { - // return nil, xerrors.New("failed to push datapoints") - // }, - // expectedError: true, - // expectedCalls: 1, - // }, + { + name: "SuccessfulMonitoringLongRun", + configFetcher: func(_ context.Context, _ *proto.GetResourcesMonitoringConfigurationRequest) (*proto.GetResourcesMonitoringConfigurationResponse, error) { + return &proto.GetResourcesMonitoringConfigurationResponse{ + Enabled: true, + Config: &proto.GetResourcesMonitoringConfigurationResponse_Config{ + NumDatapoints: 20, + TickInterval: 1, + }, + MonitoredVolumes: []string{"/"}, + }, nil + }, + datapointsPusher: func(_ context.Context, _ *proto.PushResourcesMonitoringUsageRequest) (*proto.PushResourcesMonitoringUsageResponse, error) { + return &proto.PushResourcesMonitoringUsageResponse{}, nil + }, + expectedError: false, + numTicks: 60, + counterCalls: 0, + expectedCalls: 41, + }, + { + name: "FailedToFetchConfiguration", + configFetcher: func(_ context.Context, _ *proto.GetResourcesMonitoringConfigurationRequest) (*proto.GetResourcesMonitoringConfigurationResponse, error) { + return &proto.GetResourcesMonitoringConfigurationResponse{}, xerrors.New("failed to fetch configuration") + }, + datapointsPusher: func(_ context.Context, _ *proto.PushResourcesMonitoringUsageRequest) (*proto.PushResourcesMonitoringUsageResponse, error) { + return &proto.PushResourcesMonitoringUsageResponse{}, nil + }, + expectedError: true, + numTicks: 10, + counterCalls: 0, + expectedCalls: 0, + }, } for _, tt := range tests { @@ -101,7 +94,6 @@ func TestPushResourcesMonitoringWithConfig(t *testing.T) { datapointsPusher := func(ctx context.Context, params *proto.PushResourcesMonitoringUsageRequest) (*proto.PushResourcesMonitoringUsageResponse, error) { tt.counterCalls++ - t.Logf("pushing datapoints: %v", tt.counterCalls) return tt.datapointsPusher(ctx, params) } @@ -110,6 +102,10 @@ func TestPushResourcesMonitoringWithConfig(t *testing.T) { t.Errorf("expected error: %v, got: %v", tt.expectedError, err) } + if tt.expectedError { + return + } + for i := 0; i < tt.numTicks; i++ { _, waiter := clk.AdvanceNext() waiter.Wait(ctx) From 06adbf74bc17311a1f97232ce7b0b0e603e234bc Mon Sep 17 00:00:00 2001 From: defelmnq Date: Tue, 11 Feb 2025 05:11:19 +0000 Subject: [PATCH 14/32] improve error messages --- agent/resources_monitor.go | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/agent/resources_monitor.go b/agent/resources_monitor.go index 6f68135f2bb8a..d49cfd2b3d4ad 100644 --- a/agent/resources_monitor.go +++ b/agent/resources_monitor.go @@ -15,9 +15,6 @@ import ( func (a *agent) pushResourcesMonitoring(ctx context.Context, aAPI proto.DRPCAgentClient24) error { logger := a.logger.Named("resources_monitor") - ctx, cancel := context.WithCancel(ctx) - defer cancel() - clk := quartz.NewReal() return PushResourcesMonitoringWithConfig(ctx, logger, clk, aAPI.GetResourcesMonitoringConfiguration, aAPI.PushResourcesMonitoringUsage) @@ -40,7 +37,7 @@ func PushResourcesMonitoringWithConfig(ctx context.Context, } if !config.Enabled { - logger.Info(ctx, "resources monitoring is disabled") + logger.Info(ctx, "resources monitoring is disabled - skipping") return nil } @@ -63,7 +60,7 @@ func PushResourcesMonitoringWithConfig(ctx context.Context, volTotal, volUsed, err := fetchResourceMonitoredVolume(resourcesFetcher, volume) if err != nil { logger.Error(ctx, "failed to fetch volume", slog.Error(err)) - return nil + continue } volumes = append(volumes, &ResourcesMonitorVolumeDatapoint{ From c7b03d03011c305a3bb7234e8d444c1190e15985 Mon Sep 17 00:00:00 2001 From: defelmnq Date: Wed, 12 Feb 2025 08:38:18 +0000 Subject: [PATCH 15/32] rework architecture of resources monitor --- agent/agent.go | 16 +- agent/proto/agent.pb.go | 262 +++++++++--------- agent/proto/agent.proto | 2 +- agent/proto/agent_drpc_old.go | 2 + .../resourcesmonitor/queue.go} | 34 +-- .../resourcesmonitor/queue_test.go} | 40 +-- .../resourcesmonitor/resources_monitor.go | 130 +++++++++ .../resources_monitor_test.go | 70 +++-- agent/resources_monitor.go | 132 --------- coderd/agentapi/resources_monitoring.go | 4 +- tailnet/proto/version.go | 3 +- 11 files changed, 353 insertions(+), 342 deletions(-) rename agent/{resources_monitor_queue.go => proto/resourcesmonitor/queue.go} (53%) rename agent/{resources_monitor_queue_test.go => proto/resourcesmonitor/queue_test.go} (56%) create mode 100644 agent/proto/resourcesmonitor/resources_monitor.go rename agent/{ => proto/resourcesmonitor}/resources_monitor_test.go (52%) delete mode 100644 agent/resources_monitor.go diff --git a/agent/agent.go b/agent/agent.go index 0e60f1d030e53..baff5c0f71f16 100644 --- a/agent/agent.go +++ b/agent/agent.go @@ -37,6 +37,7 @@ import ( "github.com/coder/coder/v2/agent/agentscripts" "github.com/coder/coder/v2/agent/agentssh" "github.com/coder/coder/v2/agent/proto" + "github.com/coder/coder/v2/agent/proto/resourcesmonitor" "github.com/coder/coder/v2/agent/reconnectingpty" "github.com/coder/coder/v2/buildinfo" "github.com/coder/coder/v2/cli/gitauth" @@ -46,6 +47,7 @@ import ( "github.com/coder/coder/v2/codersdk/workspacesdk" "github.com/coder/coder/v2/tailnet" tailnetproto "github.com/coder/coder/v2/tailnet/proto" + "github.com/coder/quartz" "github.com/coder/retry" ) @@ -785,7 +787,19 @@ func (a *agent) run() (retErr error) { // metadata reporting can cease as soon as we start gracefully shutting down connMan.startAgentAPI("report metadata", gracefulShutdownBehaviorStop, a.reportMetadata) - connMan.startAgentAPI("resources monitor", gracefulShutdownBehaviorStop, a.pushResourcesMonitoring) + // resources monitor can cease as soon as we start gracefully shutting down. + // The resources monitor is interesting when the workspace is running. + connMan.startAgentAPI("resources monitor", gracefulShutdownBehaviorStop, func(ctx context.Context, aAPI proto.DRPCAgentClient24) error { + logger := a.logger.Named("resources_monitor") + clk := quartz.NewReal() + config, err := aAPI.GetResourcesMonitoringConfiguration(ctx, &proto.GetResourcesMonitoringConfigurationRequest{}) + if err != nil { + return xerrors.Errorf("failed to get resources monitoring configuration: %w", err) + } + + resourcesmonitor := resourcesmonitor.NewResourcesMonitor(logger, clk, config, aAPI) + return resourcesmonitor.Start(ctx) + }) // channels to sync goroutines below // handle manifest diff --git a/agent/proto/agent.pb.go b/agent/proto/agent.pb.go index 109c7db90aa86..0107d1ee87109 100644 --- a/agent/proto/agent.pb.go +++ b/agent/proto/agent.pb.go @@ -2889,8 +2889,8 @@ type GetResourcesMonitoringConfigurationResponse_Config struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - NumDatapoints int32 `protobuf:"varint,1,opt,name=num_datapoints,json=numDatapoints,proto3" json:"num_datapoints,omitempty"` - TickInterval int32 `protobuf:"varint,2,opt,name=tick_interval,json=tickInterval,proto3" json:"tick_interval,omitempty"` // expressed in seconds + NumDatapoints int32 `protobuf:"varint,1,opt,name=num_datapoints,json=numDatapoints,proto3" json:"num_datapoints,omitempty"` + CollectionIntervalSeconds int32 `protobuf:"varint,2,opt,name=collection_interval_seconds,json=collectionIntervalSeconds,proto3" json:"collection_interval_seconds,omitempty"` } func (x *GetResourcesMonitoringConfigurationResponse_Config) Reset() { @@ -2932,9 +2932,9 @@ func (x *GetResourcesMonitoringConfigurationResponse_Config) GetNumDatapoints() return 0 } -func (x *GetResourcesMonitoringConfigurationResponse_Config) GetTickInterval() int32 { +func (x *GetResourcesMonitoringConfigurationResponse_Config) GetCollectionIntervalSeconds() int32 { if x != nil { - return x.TickInterval + return x.CollectionIntervalSeconds } return 0 } @@ -3517,7 +3517,7 @@ var file_agent_proto_agent_proto_rawDesc = []byte{ 0x4e, 0x10, 0x03, 0x22, 0x2c, 0x0a, 0x2a, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x22, 0xa6, 0x02, 0x0a, 0x2b, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x74, 0x22, 0xc1, 0x02, 0x0a, 0x2b, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, @@ -3530,140 +3530,142 @@ var file_agent_proto_agent_proto_rawDesc = []byte{ 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x2b, 0x0a, 0x11, 0x6d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x65, 0x64, 0x5f, 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x10, 0x6d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x65, 0x64, 0x56, 0x6f, 0x6c, - 0x75, 0x6d, 0x65, 0x73, 0x1a, 0x54, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x25, + 0x75, 0x6d, 0x65, 0x73, 0x1a, 0x6f, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x25, 0x0a, 0x0e, 0x6e, 0x75, 0x6d, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x6e, 0x75, 0x6d, 0x44, 0x61, 0x74, 0x61, 0x70, - 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x12, 0x23, 0x0a, 0x0d, 0x74, 0x69, 0x63, 0x6b, 0x5f, 0x69, 0x6e, - 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0c, 0x74, 0x69, - 0x63, 0x6b, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x22, 0xa3, 0x04, 0x0a, 0x23, 0x50, + 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x12, 0x3e, 0x0a, 0x1b, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x5f, 0x73, 0x65, 0x63, + 0x6f, 0x6e, 0x64, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x19, 0x63, 0x6f, 0x6c, 0x6c, + 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x53, 0x65, + 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x22, 0xa3, 0x04, 0x0a, 0x23, 0x50, 0x75, 0x73, 0x68, 0x52, 0x65, + 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, + 0x67, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x5d, 0x0a, + 0x0a, 0x64, 0x61, 0x74, 0x61, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x3d, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, + 0x76, 0x32, 0x2e, 0x50, 0x75, 0x73, 0x68, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, + 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x70, 0x6f, 0x69, 0x6e, 0x74, + 0x52, 0x0a, 0x64, 0x61, 0x74, 0x61, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x1a, 0x9c, 0x03, 0x0a, + 0x09, 0x44, 0x61, 0x74, 0x61, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x3d, 0x0a, 0x0c, 0x63, 0x6f, + 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0b, 0x63, 0x6f, + 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x61, 0x0a, 0x06, 0x6d, 0x65, 0x6d, + 0x6f, 0x72, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x49, 0x2e, 0x63, 0x6f, 0x64, 0x65, + 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x50, 0x75, 0x73, 0x68, 0x52, + 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, + 0x6e, 0x67, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x44, + 0x61, 0x74, 0x61, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x2e, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x55, + 0x73, 0x61, 0x67, 0x65, 0x52, 0x06, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x12, 0x63, 0x0a, 0x07, + 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x49, 0x2e, + 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x50, 0x75, 0x73, 0x68, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x12, 0x5d, 0x0a, 0x0a, 0x64, 0x61, 0x74, 0x61, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, - 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x3d, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, - 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x50, 0x75, 0x73, 0x68, 0x52, 0x65, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x73, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x55, - 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x44, 0x61, 0x74, 0x61, - 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, 0x0a, 0x64, 0x61, 0x74, 0x61, 0x70, 0x6f, 0x69, 0x6e, 0x74, - 0x73, 0x1a, 0x9c, 0x03, 0x0a, 0x09, 0x44, 0x61, 0x74, 0x61, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, - 0x3d, 0x0a, 0x0c, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, - 0x70, 0x52, 0x0b, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x61, - 0x0a, 0x06, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x49, + 0x73, 0x74, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x2e, 0x56, 0x6f, 0x6c, + 0x75, 0x6d, 0x65, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x07, 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, + 0x73, 0x1a, 0x37, 0x0a, 0x0b, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x55, 0x73, 0x61, 0x67, 0x65, + 0x12, 0x12, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, + 0x75, 0x73, 0x65, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x1a, 0x4f, 0x0a, 0x0b, 0x56, 0x6f, + 0x6c, 0x75, 0x6d, 0x65, 0x55, 0x73, 0x61, 0x67, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x76, 0x6f, 0x6c, + 0x75, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x76, 0x6f, 0x6c, 0x75, 0x6d, + 0x65, 0x12, 0x12, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, + 0x04, 0x75, 0x73, 0x65, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x22, 0x26, 0x0a, 0x24, 0x50, + 0x75, 0x73, 0x68, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x4d, 0x6f, 0x6e, 0x69, + 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x2a, 0x63, 0x0a, 0x09, 0x41, 0x70, 0x70, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, + 0x12, 0x1a, 0x0a, 0x16, 0x41, 0x50, 0x50, 0x5f, 0x48, 0x45, 0x41, 0x4c, 0x54, 0x48, 0x5f, 0x55, + 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0c, 0x0a, 0x08, + 0x44, 0x49, 0x53, 0x41, 0x42, 0x4c, 0x45, 0x44, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x49, 0x4e, + 0x49, 0x54, 0x49, 0x41, 0x4c, 0x49, 0x5a, 0x49, 0x4e, 0x47, 0x10, 0x02, 0x12, 0x0b, 0x0a, 0x07, + 0x48, 0x45, 0x41, 0x4c, 0x54, 0x48, 0x59, 0x10, 0x03, 0x12, 0x0d, 0x0a, 0x09, 0x55, 0x4e, 0x48, + 0x45, 0x41, 0x4c, 0x54, 0x48, 0x59, 0x10, 0x04, 0x32, 0x9c, 0x0a, 0x0a, 0x05, 0x41, 0x67, 0x65, + 0x6e, 0x74, 0x12, 0x4b, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x4d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, + 0x74, 0x12, 0x22, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, + 0x76, 0x32, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, + 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x4d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x12, + 0x5a, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x42, 0x61, 0x6e, + 0x6e, 0x65, 0x72, 0x12, 0x27, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, + 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x42, + 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x63, + 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x53, 0x65, + 0x72, 0x76, 0x69, 0x63, 0x65, 0x42, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x12, 0x56, 0x0a, 0x0b, 0x55, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x22, 0x2e, 0x63, 0x6f, 0x64, + 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x55, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, - 0x50, 0x75, 0x73, 0x68, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x4d, 0x6f, 0x6e, - 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x2e, 0x4d, 0x65, - 0x6d, 0x6f, 0x72, 0x79, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x06, 0x6d, 0x65, 0x6d, 0x6f, 0x72, - 0x79, 0x12, 0x63, 0x0a, 0x07, 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, - 0x28, 0x0b, 0x32, 0x49, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, - 0x2e, 0x76, 0x32, 0x2e, 0x50, 0x75, 0x73, 0x68, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x73, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x55, 0x73, 0x61, 0x67, 0x65, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x70, 0x6f, 0x69, 0x6e, - 0x74, 0x2e, 0x56, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x07, 0x76, - 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x73, 0x1a, 0x37, 0x0a, 0x0b, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, - 0x55, 0x73, 0x61, 0x67, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x64, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x04, 0x75, 0x73, 0x65, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x74, - 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x1a, - 0x4f, 0x0a, 0x0b, 0x56, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x55, 0x73, 0x61, 0x67, 0x65, 0x12, 0x16, - 0x0a, 0x06, 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, - 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x64, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x75, 0x73, 0x65, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, - 0x74, 0x61, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, - 0x22, 0x26, 0x0a, 0x24, 0x50, 0x75, 0x73, 0x68, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x73, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x55, 0x73, 0x61, 0x67, 0x65, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2a, 0x63, 0x0a, 0x09, 0x41, 0x70, 0x70, 0x48, - 0x65, 0x61, 0x6c, 0x74, 0x68, 0x12, 0x1a, 0x0a, 0x16, 0x41, 0x50, 0x50, 0x5f, 0x48, 0x45, 0x41, - 0x4c, 0x54, 0x48, 0x5f, 0x55, 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, - 0x00, 0x12, 0x0c, 0x0a, 0x08, 0x44, 0x49, 0x53, 0x41, 0x42, 0x4c, 0x45, 0x44, 0x10, 0x01, 0x12, - 0x10, 0x0a, 0x0c, 0x49, 0x4e, 0x49, 0x54, 0x49, 0x41, 0x4c, 0x49, 0x5a, 0x49, 0x4e, 0x47, 0x10, - 0x02, 0x12, 0x0b, 0x0a, 0x07, 0x48, 0x45, 0x41, 0x4c, 0x54, 0x48, 0x59, 0x10, 0x03, 0x12, 0x0d, - 0x0a, 0x09, 0x55, 0x4e, 0x48, 0x45, 0x41, 0x4c, 0x54, 0x48, 0x59, 0x10, 0x04, 0x32, 0x9c, 0x0a, - 0x0a, 0x05, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x12, 0x4b, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x4d, 0x61, - 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x12, 0x22, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, - 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x61, 0x6e, 0x69, 0x66, - 0x65, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x63, 0x6f, 0x64, - 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x4d, 0x61, 0x6e, 0x69, - 0x66, 0x65, 0x73, 0x74, 0x12, 0x5a, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, - 0x63, 0x65, 0x42, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x12, 0x27, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, - 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x65, 0x72, - 0x76, 0x69, 0x63, 0x65, 0x42, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x1d, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, - 0x76, 0x32, 0x2e, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x42, 0x61, 0x6e, 0x6e, 0x65, 0x72, - 0x12, 0x56, 0x0a, 0x0b, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, - 0x22, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, - 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, - 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x0f, 0x55, 0x70, 0x64, 0x61, - 0x74, 0x65, 0x4c, 0x69, 0x66, 0x65, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x12, 0x26, 0x2e, 0x63, 0x6f, - 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x55, 0x70, 0x64, - 0x61, 0x74, 0x65, 0x4c, 0x69, 0x66, 0x65, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, - 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x4c, 0x69, 0x66, 0x65, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x12, 0x72, - 0x0a, 0x15, 0x42, 0x61, 0x74, 0x63, 0x68, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x70, 0x70, - 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x73, 0x12, 0x2b, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, - 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x55, 0x70, - 0x64, 0x61, 0x74, 0x65, 0x41, 0x70, 0x70, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, + 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x0f, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x66, + 0x65, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x12, 0x26, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, + 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4c, 0x69, + 0x66, 0x65, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, + 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, + 0x4c, 0x69, 0x66, 0x65, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x12, 0x72, 0x0a, 0x15, 0x42, 0x61, 0x74, + 0x63, 0x68, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x70, 0x70, 0x48, 0x65, 0x61, 0x6c, 0x74, + 0x68, 0x73, 0x12, 0x2b, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, + 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, + 0x70, 0x70, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x2c, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, + 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x70, 0x70, 0x48, + 0x65, 0x61, 0x6c, 0x74, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4e, 0x0a, + 0x0d, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x12, 0x24, + 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, + 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, + 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x12, 0x6e, 0x0a, + 0x13, 0x42, 0x61, 0x74, 0x63, 0x68, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x74, 0x61, + 0x64, 0x61, 0x74, 0x61, 0x12, 0x2a, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x55, 0x70, 0x64, 0x61, 0x74, - 0x65, 0x41, 0x70, 0x70, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x4e, 0x0a, 0x0d, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x74, 0x61, 0x72, - 0x74, 0x75, 0x70, 0x12, 0x24, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, - 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x74, 0x61, 0x72, 0x74, - 0x75, 0x70, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x63, 0x6f, 0x64, 0x65, - 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, - 0x75, 0x70, 0x12, 0x6e, 0x0a, 0x13, 0x42, 0x61, 0x74, 0x63, 0x68, 0x55, 0x70, 0x64, 0x61, 0x74, - 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x2a, 0x2e, 0x63, 0x6f, 0x64, 0x65, - 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, - 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2b, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, - 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x55, 0x70, 0x64, 0x61, - 0x74, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x62, 0x0a, 0x0f, 0x42, 0x61, 0x74, 0x63, 0x68, 0x43, 0x72, 0x65, 0x61, 0x74, - 0x65, 0x4c, 0x6f, 0x67, 0x73, 0x12, 0x26, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, - 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x43, 0x72, 0x65, 0x61, - 0x74, 0x65, 0x4c, 0x6f, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, - 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x42, - 0x61, 0x74, 0x63, 0x68, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4c, 0x6f, 0x67, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x77, 0x0a, 0x16, 0x47, 0x65, 0x74, 0x41, 0x6e, 0x6e, - 0x6f, 0x75, 0x6e, 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x42, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x73, - 0x12, 0x2d, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, - 0x32, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x6e, 0x6e, 0x6f, 0x75, 0x6e, 0x63, 0x65, 0x6d, 0x65, 0x6e, - 0x74, 0x42, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x2e, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, - 0x2e, 0x47, 0x65, 0x74, 0x41, 0x6e, 0x6e, 0x6f, 0x75, 0x6e, 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, - 0x42, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x7e, 0x0a, 0x0f, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, - 0x65, 0x64, 0x12, 0x34, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, - 0x2e, 0x76, 0x32, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x41, 0x67, 0x65, - 0x6e, 0x74, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, - 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, - 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, - 0x61, 0x63, 0x65, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x43, 0x6f, - 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, - 0x9e, 0x01, 0x0a, 0x23, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, + 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x2b, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, + 0x32, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x74, + 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x62, 0x0a, + 0x0f, 0x42, 0x61, 0x74, 0x63, 0x68, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4c, 0x6f, 0x67, 0x73, + 0x12, 0x26, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, + 0x32, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4c, 0x6f, 0x67, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, + 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x43, + 0x72, 0x65, 0x61, 0x74, 0x65, 0x4c, 0x6f, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, + 0x65, 0x12, 0x77, 0x0a, 0x16, 0x47, 0x65, 0x74, 0x41, 0x6e, 0x6e, 0x6f, 0x75, 0x6e, 0x63, 0x65, + 0x6d, 0x65, 0x6e, 0x74, 0x42, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x73, 0x12, 0x2d, 0x2e, 0x63, 0x6f, + 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x47, 0x65, 0x74, + 0x41, 0x6e, 0x6e, 0x6f, 0x75, 0x6e, 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x42, 0x61, 0x6e, 0x6e, + 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x63, 0x6f, 0x64, + 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x47, 0x65, 0x74, 0x41, + 0x6e, 0x6e, 0x6f, 0x75, 0x6e, 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x42, 0x61, 0x6e, 0x6e, 0x65, + 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x7e, 0x0a, 0x0f, 0x53, 0x63, + 0x72, 0x69, 0x70, 0x74, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x12, 0x34, 0x2e, + 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x57, + 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x53, 0x63, 0x72, + 0x69, 0x70, 0x74, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, + 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x41, 0x67, + 0x65, 0x6e, 0x74, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, + 0x65, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x9e, 0x01, 0x0a, 0x23, 0x47, + 0x65, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x4d, 0x6f, 0x6e, 0x69, 0x74, + 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x12, 0x3a, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, + 0x2e, 0x76, 0x32, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x3a, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, - 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x73, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x43, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x3b, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, - 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x73, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x89, 0x01, 0x0a, 0x1c, 0x50, 0x75, 0x73, 0x68, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x73, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x55, 0x73, 0x61, 0x67, - 0x65, 0x12, 0x33, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, + 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3b, + 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, + 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x4d, 0x6f, 0x6e, 0x69, + 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x89, 0x01, 0x0a, 0x1c, + 0x50, 0x75, 0x73, 0x68, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x4d, 0x6f, 0x6e, + 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x55, 0x73, 0x61, 0x67, 0x65, 0x12, 0x33, 0x2e, 0x63, + 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x50, 0x75, + 0x73, 0x68, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x4d, 0x6f, 0x6e, 0x69, 0x74, + 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x34, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x50, 0x75, 0x73, 0x68, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x34, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, - 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x50, 0x75, 0x73, 0x68, 0x52, 0x65, 0x73, 0x6f, - 0x75, 0x72, 0x63, 0x65, 0x73, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x55, - 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x27, 0x5a, 0x25, - 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x6f, 0x64, 0x65, 0x72, - 0x2f, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2f, 0x76, 0x32, 0x2f, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2f, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x27, 0x5a, 0x25, 0x67, 0x69, 0x74, 0x68, 0x75, + 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2f, 0x63, 0x6f, 0x64, 0x65, + 0x72, 0x2f, 0x76, 0x32, 0x2f, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( diff --git a/agent/proto/agent.proto b/agent/proto/agent.proto index b2a9d010bf026..7c02bd4a1cfc5 100644 --- a/agent/proto/agent.proto +++ b/agent/proto/agent.proto @@ -302,7 +302,7 @@ message GetResourcesMonitoringConfigurationResponse { bool enabled = 1; message Config { int32 num_datapoints = 1; - int32 tick_interval = 2; // expressed in seconds + int32 collection_interval_seconds = 2; } Config config = 2; repeated string monitored_volumes = 3; diff --git a/agent/proto/agent_drpc_old.go b/agent/proto/agent_drpc_old.go index bf1668b8f7483..f1db351428e9b 100644 --- a/agent/proto/agent_drpc_old.go +++ b/agent/proto/agent_drpc_old.go @@ -41,6 +41,8 @@ type DRPCAgentClient23 interface { ScriptCompleted(ctx context.Context, in *WorkspaceAgentScriptCompletedRequest) (*WorkspaceAgentScriptCompletedResponse, error) } +// DRPCAgentClient24 is the Agent API at v2.4. It adds the GetResourcesMonitoringConfiguration and +// PushResourcesMonitoringUsage RPCs. Compatible with Coder v2.19+ type DRPCAgentClient24 interface { DRPCAgentClient23 GetResourcesMonitoringConfiguration(ctx context.Context, in *GetResourcesMonitoringConfigurationRequest) (*GetResourcesMonitoringConfigurationResponse, error) diff --git a/agent/resources_monitor_queue.go b/agent/proto/resourcesmonitor/queue.go similarity index 53% rename from agent/resources_monitor_queue.go rename to agent/proto/resourcesmonitor/queue.go index 1046ab9e6515e..65b61ee209f9d 100644 --- a/agent/resources_monitor_queue.go +++ b/agent/proto/resourcesmonitor/queue.go @@ -1,41 +1,41 @@ -package agent +package resourcesmonitor import ( "github.com/coder/coder/v2/agent/proto" ) -type ResourcesMonitorDatapoint struct { - Memory *ResourcesMonitorMemoryDatapoint - Volumes []*ResourcesMonitorVolumeDatapoint +type Datapoint struct { + Memory *MemoryDatapoint + Volumes []*VolumeDatapoint } -type ResourcesMonitorMemoryDatapoint struct { +type MemoryDatapoint struct { Total int64 Used int64 } -type ResourcesMonitorVolumeDatapoint struct { +type VolumeDatapoint struct { Path string Total int64 Used int64 } -// ResourcesMonitorQueue represents a FIFO queue with a fixed size -type ResourcesMonitorQueue struct { - items []ResourcesMonitorDatapoint +// Queue represents a FIFO queue with a fixed size +type Queue struct { + items []Datapoint size int } -// newResourcesMonitorQueue creates a new ResourcesMonitorQueue with the given size -func NewResourcesMonitorQueue(size int) *ResourcesMonitorQueue { - return &ResourcesMonitorQueue{ - items: make([]ResourcesMonitorDatapoint, 0, size), +// newQueue creates a new Queue with the given size +func NewQueue(size int) *Queue { + return &Queue{ + items: make([]Datapoint, 0, size), size: size, } } // Push adds a new item to the queue -func (q *ResourcesMonitorQueue) Push(item ResourcesMonitorDatapoint) { +func (q *Queue) Push(item Datapoint) { if len(q.items) >= q.size { // Remove the first item (FIFO) q.items = q.items[1:] @@ -43,15 +43,15 @@ func (q *ResourcesMonitorQueue) Push(item ResourcesMonitorDatapoint) { q.items = append(q.items, item) } -func (q *ResourcesMonitorQueue) IsFull() bool { +func (q *Queue) IsFull() bool { return len(q.items) == q.size } -func (q *ResourcesMonitorQueue) Items() []ResourcesMonitorDatapoint { +func (q *Queue) Items() []Datapoint { return q.items } -func (q *ResourcesMonitorQueue) ItemsAsProto() []*proto.PushResourcesMonitoringUsageRequest_Datapoint { +func (q *Queue) ItemsAsProto() []*proto.PushResourcesMonitoringUsageRequest_Datapoint { items := make([]*proto.PushResourcesMonitoringUsageRequest_Datapoint, 0, len(q.items)) for _, item := range q.items { diff --git a/agent/resources_monitor_queue_test.go b/agent/proto/resourcesmonitor/queue_test.go similarity index 56% rename from agent/resources_monitor_queue_test.go rename to agent/proto/resourcesmonitor/queue_test.go index 079c0f62c672b..320082723e66d 100644 --- a/agent/resources_monitor_queue_test.go +++ b/agent/proto/resourcesmonitor/queue_test.go @@ -1,9 +1,9 @@ -package agent_test +package resourcesmonitor_test import ( "testing" - "github.com/coder/coder/v2/agent" + "github.com/coder/coder/v2/agent/proto/resourcesmonitor" ) func TestResourceMonitorQueue(t *testing.T) { @@ -12,30 +12,30 @@ func TestResourceMonitorQueue(t *testing.T) { tests := []struct { name string pushCount int - expected []agent.ResourcesMonitorDatapoint + expected []resourcesmonitor.Datapoint }{ { name: "Push zero", pushCount: 0, - expected: []agent.ResourcesMonitorDatapoint{}, + expected: []resourcesmonitor.Datapoint{}, }, { name: "Push less than capacity", pushCount: 3, - expected: []agent.ResourcesMonitorDatapoint{ - {Memory: &agent.ResourcesMonitorMemoryDatapoint{Total: 1, Used: 1}}, - {Memory: &agent.ResourcesMonitorMemoryDatapoint{Total: 2, Used: 2}}, - {Memory: &agent.ResourcesMonitorMemoryDatapoint{Total: 3, Used: 3}}, + expected: []resourcesmonitor.Datapoint{ + {Memory: &resourcesmonitor.MemoryDatapoint{Total: 1, Used: 1}}, + {Memory: &resourcesmonitor.MemoryDatapoint{Total: 2, Used: 2}}, + {Memory: &resourcesmonitor.MemoryDatapoint{Total: 3, Used: 3}}, }, }, { name: "Push exactly capacity", pushCount: 20, - expected: func() []agent.ResourcesMonitorDatapoint { - var result []agent.ResourcesMonitorDatapoint + expected: func() []resourcesmonitor.Datapoint { + var result []resourcesmonitor.Datapoint for i := 1; i <= 20; i++ { - result = append(result, agent.ResourcesMonitorDatapoint{ - Memory: &agent.ResourcesMonitorMemoryDatapoint{ + result = append(result, resourcesmonitor.Datapoint{ + Memory: &resourcesmonitor.MemoryDatapoint{ Total: int64(i), Used: int64(i), }, @@ -47,11 +47,11 @@ func TestResourceMonitorQueue(t *testing.T) { { name: "Push more than capacity", pushCount: 25, - expected: func() []agent.ResourcesMonitorDatapoint { - var result []agent.ResourcesMonitorDatapoint + expected: func() []resourcesmonitor.Datapoint { + var result []resourcesmonitor.Datapoint for i := 6; i <= 25; i++ { - result = append(result, agent.ResourcesMonitorDatapoint{ - Memory: &agent.ResourcesMonitorMemoryDatapoint{ + result = append(result, resourcesmonitor.Datapoint{ + Memory: &resourcesmonitor.MemoryDatapoint{ Total: int64(i), Used: int64(i), }, @@ -67,10 +67,10 @@ func TestResourceMonitorQueue(t *testing.T) { t.Run(tt.name, func(t *testing.T) { t.Parallel() - queue := agent.NewResourcesMonitorQueue(20) + queue := resourcesmonitor.NewQueue(20) for i := 1; i <= tt.pushCount; i++ { - queue.Push(agent.ResourcesMonitorDatapoint{ - Memory: &agent.ResourcesMonitorMemoryDatapoint{ + queue.Push(resourcesmonitor.Datapoint{ + Memory: &resourcesmonitor.MemoryDatapoint{ Total: int64(i), Used: int64(i), }, @@ -89,7 +89,7 @@ func TestResourceMonitorQueue(t *testing.T) { } } -func equal(a, b []agent.ResourcesMonitorDatapoint) bool { +func equal(a, b []resourcesmonitor.Datapoint) bool { if len(a) != len(b) { return false } diff --git a/agent/proto/resourcesmonitor/resources_monitor.go b/agent/proto/resourcesmonitor/resources_monitor.go new file mode 100644 index 0000000000000..3c3db35233a67 --- /dev/null +++ b/agent/proto/resourcesmonitor/resources_monitor.go @@ -0,0 +1,130 @@ +package resourcesmonitor + +import ( + "context" + "time" + + "golang.org/x/xerrors" + + "cdr.dev/slog" + "github.com/coder/coder/v2/agent/proto" + "github.com/coder/coder/v2/cli/clistat" + "github.com/coder/quartz" +) + +type monitor struct { + logger slog.Logger + clock quartz.Clock + config *proto.GetResourcesMonitoringConfigurationResponse + datapointsPusher datapointsPusher +} + +//nolint:revive +func NewResourcesMonitor(logger slog.Logger, clock quartz.Clock, config *proto.GetResourcesMonitoringConfigurationResponse, datapointsPusher datapointsPusher) *monitor { + return &monitor{ + logger: logger, + clock: clock, + config: config, + datapointsPusher: datapointsPusher, + } +} + +type datapointsPusher interface { + PushResourcesMonitoringUsage(ctx context.Context, req *proto.PushResourcesMonitoringUsageRequest) (*proto.PushResourcesMonitoringUsageResponse, error) +} + +func (m *monitor) Start(ctx context.Context) error { + if !m.config.Enabled { + m.logger.Info(ctx, "resources monitoring is disabled - skipping") + return nil + } + + resourcesFetcher, err := clistat.New() + if err != nil { + return xerrors.Errorf("failed to create resources fetcher: %w", err) + } + + datapointsQueue := NewQueue(int(m.config.Config.NumDatapoints)) + + m.clock.TickerFunc(ctx, time.Duration(m.config.Config.CollectionIntervalSeconds*int32(time.Second)), func() error { + memTotal, memUsed, err := m.fetchResourceMonitoredMemory(resourcesFetcher) + if err != nil { + m.logger.Error(ctx, "failed to fetch memory", slog.Error(err)) + return nil + } + + volumes := make([]*VolumeDatapoint, 0, len(m.config.MonitoredVolumes)) + for _, volume := range m.config.MonitoredVolumes { + volTotal, volUsed, err := m.fetchResourceMonitoredVolume(resourcesFetcher, volume) + if err != nil { + m.logger.Error(ctx, "failed to fetch volume", slog.Error(err)) + continue + } + + volumes = append(volumes, &VolumeDatapoint{ + Path: volume, + Total: volTotal, + Used: volUsed, + }) + } + + datapointsQueue.Push(Datapoint{ + Memory: &MemoryDatapoint{ + Total: memTotal, + Used: memUsed, + }, + Volumes: volumes, + }) + + if datapointsQueue.IsFull() { + _, err = m.datapointsPusher.PushResourcesMonitoringUsage(ctx, &proto.PushResourcesMonitoringUsageRequest{ + Datapoints: datapointsQueue.ItemsAsProto(), + }) + if err != nil { + m.logger.Error(ctx, "failed to push resources monitoring usage", slog.Error(err)) + } + } + + return nil + }, "resources_monitor") + + return nil +} + +func (m *monitor) fetchResourceMonitoredMemory(fetcher *clistat.Statter) (total int64, used int64, err error) { + mem, err := fetcher.HostMemory(clistat.PrefixMebi) + if err != nil { + return 0, 0, err + } + + var memTotal, memUsed int64 + if mem.Total == nil { + return 0, 0, xerrors.New("memory total is nil - can not fetch memory") + } + + memTotal = m.bytesToMegabytes(int64(*mem.Total)) + memUsed = m.bytesToMegabytes(int64(mem.Used)) + + return memTotal, memUsed, nil +} + +func (m *monitor) fetchResourceMonitoredVolume(fetcher *clistat.Statter, volume string) (total int64, used int64, err error) { + vol, err := fetcher.Disk(clistat.PrefixMebi, volume) + if err != nil { + return 0, 0, err + } + + var volTotal, volUsed int64 + if vol.Total == nil { + return 0, 0, xerrors.New("volume total is nil - can not fetch volume") + } + + volTotal = m.bytesToMegabytes(int64(*vol.Total)) + volUsed = m.bytesToMegabytes(int64(vol.Used)) + + return volTotal, volUsed, nil +} + +func (*monitor) bytesToMegabytes(bytes int64) int64 { + return bytes / (1024 * 1024) +} diff --git a/agent/resources_monitor_test.go b/agent/proto/resourcesmonitor/resources_monitor_test.go similarity index 52% rename from agent/resources_monitor_test.go rename to agent/proto/resourcesmonitor/resources_monitor_test.go index 6f819c99435fe..33447ed1199f2 100644 --- a/agent/resources_monitor_test.go +++ b/agent/proto/resourcesmonitor/resources_monitor_test.go @@ -1,26 +1,32 @@ -package agent_test +package resourcesmonitor_test import ( "context" "os" "testing" - "golang.org/x/xerrors" - "cdr.dev/slog" "cdr.dev/slog/sloggers/sloghuman" - "github.com/coder/coder/v2/agent" "github.com/coder/coder/v2/agent/proto" + "github.com/coder/coder/v2/agent/proto/resourcesmonitor" "github.com/coder/quartz" ) +type datapointsPusherMock struct { + PushResourcesMonitoringUsageFunc func(ctx context.Context, req *proto.PushResourcesMonitoringUsageRequest) (*proto.PushResourcesMonitoringUsageResponse, error) +} + +func (d *datapointsPusherMock) PushResourcesMonitoringUsage(ctx context.Context, req *proto.PushResourcesMonitoringUsageRequest) (*proto.PushResourcesMonitoringUsageResponse, error) { + return d.PushResourcesMonitoringUsageFunc(ctx, req) +} + func TestPushResourcesMonitoringWithConfig(t *testing.T) { t.Parallel() tests := []struct { name string - configFetcher agent.ResourcesMonitorConfigurationFetcher - datapointsPusher agent.ResourcesMonitorDatapointsPusher + config *proto.GetResourcesMonitoringConfigurationResponse + datapointsPusher func(ctx context.Context, req *proto.PushResourcesMonitoringUsageRequest) (*proto.PushResourcesMonitoringUsageResponse, error) expectedError bool numTicks int counterCalls int @@ -28,15 +34,13 @@ func TestPushResourcesMonitoringWithConfig(t *testing.T) { }{ { name: "SuccessfulMonitoring", - configFetcher: func(_ context.Context, _ *proto.GetResourcesMonitoringConfigurationRequest) (*proto.GetResourcesMonitoringConfigurationResponse, error) { - return &proto.GetResourcesMonitoringConfigurationResponse{ - Enabled: true, - Config: &proto.GetResourcesMonitoringConfigurationResponse_Config{ - NumDatapoints: 20, - TickInterval: 1, - }, - MonitoredVolumes: []string{"/"}, - }, nil + config: &proto.GetResourcesMonitoringConfigurationResponse{ + Enabled: true, + Config: &proto.GetResourcesMonitoringConfigurationResponse_Config{ + NumDatapoints: 20, + CollectionIntervalSeconds: 1, + }, + MonitoredVolumes: []string{"/"}, }, datapointsPusher: func(_ context.Context, _ *proto.PushResourcesMonitoringUsageRequest) (*proto.PushResourcesMonitoringUsageResponse, error) { return &proto.PushResourcesMonitoringUsageResponse{}, nil @@ -48,15 +52,13 @@ func TestPushResourcesMonitoringWithConfig(t *testing.T) { }, { name: "SuccessfulMonitoringLongRun", - configFetcher: func(_ context.Context, _ *proto.GetResourcesMonitoringConfigurationRequest) (*proto.GetResourcesMonitoringConfigurationResponse, error) { - return &proto.GetResourcesMonitoringConfigurationResponse{ - Enabled: true, - Config: &proto.GetResourcesMonitoringConfigurationResponse_Config{ - NumDatapoints: 20, - TickInterval: 1, - }, - MonitoredVolumes: []string{"/"}, - }, nil + config: &proto.GetResourcesMonitoringConfigurationResponse{ + Enabled: true, + Config: &proto.GetResourcesMonitoringConfigurationResponse_Config{ + NumDatapoints: 20, + CollectionIntervalSeconds: 1, + }, + MonitoredVolumes: []string{"/"}, }, datapointsPusher: func(_ context.Context, _ *proto.PushResourcesMonitoringUsageRequest) (*proto.PushResourcesMonitoringUsageResponse, error) { return &proto.PushResourcesMonitoringUsageResponse{}, nil @@ -66,19 +68,6 @@ func TestPushResourcesMonitoringWithConfig(t *testing.T) { counterCalls: 0, expectedCalls: 41, }, - { - name: "FailedToFetchConfiguration", - configFetcher: func(_ context.Context, _ *proto.GetResourcesMonitoringConfigurationRequest) (*proto.GetResourcesMonitoringConfigurationResponse, error) { - return &proto.GetResourcesMonitoringConfigurationResponse{}, xerrors.New("failed to fetch configuration") - }, - datapointsPusher: func(_ context.Context, _ *proto.PushResourcesMonitoringUsageRequest) (*proto.PushResourcesMonitoringUsageResponse, error) { - return &proto.PushResourcesMonitoringUsageResponse{}, nil - }, - expectedError: true, - numTicks: 10, - counterCalls: 0, - expectedCalls: 0, - }, } for _, tt := range tests { @@ -97,7 +86,12 @@ func TestPushResourcesMonitoringWithConfig(t *testing.T) { return tt.datapointsPusher(ctx, params) } - err := agent.PushResourcesMonitoringWithConfig(ctx, logger, clk, tt.configFetcher, datapointsPusher) + pusher := &datapointsPusherMock{ + PushResourcesMonitoringUsageFunc: datapointsPusher, + } + + monitor := resourcesmonitor.NewResourcesMonitor(logger, clk, tt.config, pusher) + err := monitor.Start(ctx) if (err != nil) != tt.expectedError { t.Errorf("expected error: %v, got: %v", tt.expectedError, err) } diff --git a/agent/resources_monitor.go b/agent/resources_monitor.go deleted file mode 100644 index d49cfd2b3d4ad..0000000000000 --- a/agent/resources_monitor.go +++ /dev/null @@ -1,132 +0,0 @@ -package agent - -import ( - "context" - "time" - - "golang.org/x/xerrors" - - "cdr.dev/slog" - "github.com/coder/coder/v2/agent/proto" - "github.com/coder/coder/v2/cli/clistat" - "github.com/coder/quartz" -) - -func (a *agent) pushResourcesMonitoring(ctx context.Context, aAPI proto.DRPCAgentClient24) error { - logger := a.logger.Named("resources_monitor") - - clk := quartz.NewReal() - - return PushResourcesMonitoringWithConfig(ctx, logger, clk, aAPI.GetResourcesMonitoringConfiguration, aAPI.PushResourcesMonitoringUsage) -} - -type ( - ResourcesMonitorConfigurationFetcher func(ctx context.Context, params *proto.GetResourcesMonitoringConfigurationRequest) (*proto.GetResourcesMonitoringConfigurationResponse, error) - ResourcesMonitorDatapointsPusher func(ctx context.Context, params *proto.PushResourcesMonitoringUsageRequest) (*proto.PushResourcesMonitoringUsageResponse, error) -) - -func PushResourcesMonitoringWithConfig(ctx context.Context, - logger slog.Logger, - clk quartz.Clock, - configFetcher ResourcesMonitorConfigurationFetcher, - datapointsPusher ResourcesMonitorDatapointsPusher, -) error { - config, err := configFetcher(ctx, &proto.GetResourcesMonitoringConfigurationRequest{}) - if err != nil { - return xerrors.Errorf("failed to get resources monitoring configuration: %w", err) - } - - if !config.Enabled { - logger.Info(ctx, "resources monitoring is disabled - skipping") - return nil - } - - resourcesFetcher, err := clistat.New() - if err != nil { - return xerrors.Errorf("failed to create resources fetcher: %w", err) - } - - datapointsQueue := NewResourcesMonitorQueue(int(config.Config.NumDatapoints)) - - clk.TickerFunc(ctx, time.Duration(config.Config.TickInterval*int32(time.Second)), func() error { - memTotal, memUsed, err := fetchResourceMonitoredMemory(resourcesFetcher) - if err != nil { - logger.Error(ctx, "failed to fetch memory", slog.Error(err)) - return nil - } - - volumes := make([]*ResourcesMonitorVolumeDatapoint, 0, len(config.MonitoredVolumes)) - for _, volume := range config.MonitoredVolumes { - volTotal, volUsed, err := fetchResourceMonitoredVolume(resourcesFetcher, volume) - if err != nil { - logger.Error(ctx, "failed to fetch volume", slog.Error(err)) - continue - } - - volumes = append(volumes, &ResourcesMonitorVolumeDatapoint{ - Path: volume, - Total: volTotal, - Used: volUsed, - }) - } - - datapointsQueue.Push(ResourcesMonitorDatapoint{ - Memory: &ResourcesMonitorMemoryDatapoint{ - Total: memTotal, - Used: memUsed, - }, - Volumes: volumes, - }) - - if datapointsQueue.IsFull() { - _, err = datapointsPusher(ctx, &proto.PushResourcesMonitoringUsageRequest{ - Datapoints: datapointsQueue.ItemsAsProto(), - }) - if err != nil { - logger.Error(ctx, "failed to push resources monitoring usage", slog.Error(err)) - } - } - - return nil - }, "resources_monitor") - - return nil -} - -func fetchResourceMonitoredMemory(fetcher *clistat.Statter) (total int64, used int64, err error) { - mem, err := fetcher.HostMemory(clistat.PrefixMebi) - if err != nil { - return 0, 0, err - } - - var memTotal, memUsed int64 - if mem.Total == nil { - return 0, 0, xerrors.New("memory total is nil - can not fetch memory") - } - - memTotal = bytesToMegabytes(int64(*mem.Total)) - memUsed = bytesToMegabytes(int64(mem.Used)) - - return memTotal, memUsed, nil -} - -func fetchResourceMonitoredVolume(fetcher *clistat.Statter, volume string) (total int64, used int64, err error) { - vol, err := fetcher.Disk(clistat.PrefixMebi, volume) - if err != nil { - return 0, 0, err - } - - var volTotal, volUsed int64 - if vol.Total == nil { - return 0, 0, xerrors.New("volume total is nil - can not fetch volume") - } - - volTotal = bytesToMegabytes(int64(*vol.Total)) - volUsed = bytesToMegabytes(int64(vol.Used)) - - return volTotal, volUsed, nil -} - -func bytesToMegabytes(bytes int64) int64 { - return bytes / (1024 * 1024) -} diff --git a/coderd/agentapi/resources_monitoring.go b/coderd/agentapi/resources_monitoring.go index 1d44836738f75..359cb3e06241c 100644 --- a/coderd/agentapi/resources_monitoring.go +++ b/coderd/agentapi/resources_monitoring.go @@ -40,8 +40,8 @@ func (a *ResourcesMonitoringAPI) GetResourcesMonitoringConfiguration(ctx context return &proto.GetResourcesMonitoringConfigurationResponse{ Enabled: false, Config: &proto.GetResourcesMonitoringConfigurationResponse_Config{ - TickInterval: 10, - NumDatapoints: 20, + CollectionIntervalSeconds: 10, + NumDatapoints: 20, }, MonitoredVolumes: volumes, }, nil diff --git a/tailnet/proto/version.go b/tailnet/proto/version.go index 20121471f026e..8321efcc608e3 100644 --- a/tailnet/proto/version.go +++ b/tailnet/proto/version.go @@ -41,7 +41,8 @@ import ( // // API v2.4: // - Shipped in Coder v2.19.0 -// - Added support for ResourcesMonitoring RPCs on the Agent API. +// - Added support for GetResourcesMonitoringConfiguration and +// PushResourcesMonitoringUsage RPCs on the Agent API. const ( CurrentMajor = 2 CurrentMinor = 4 From 2c3d171a69dd88ae39fd7b9c93c98d03d8b92535 Mon Sep 17 00:00:00 2001 From: defelmnq Date: Wed, 12 Feb 2025 10:39:06 +0000 Subject: [PATCH 16/32] improve resourcesmonitor struct --- agent/agent.go | 8 ++++- agent/proto/resourcesmonitor/queue_test.go | 30 ++++++---------- .../resourcesmonitor/resources_monitor.go | 34 +++++++++---------- .../resources_monitor_test.go | 34 ++++++++++--------- coderd/agentapi/resources_monitoring.go | 4 ++- 5 files changed, 55 insertions(+), 55 deletions(-) diff --git a/agent/agent.go b/agent/agent.go index baff5c0f71f16..2c6b973279577 100644 --- a/agent/agent.go +++ b/agent/agent.go @@ -40,6 +40,7 @@ import ( "github.com/coder/coder/v2/agent/proto/resourcesmonitor" "github.com/coder/coder/v2/agent/reconnectingpty" "github.com/coder/coder/v2/buildinfo" + "github.com/coder/coder/v2/cli/clistat" "github.com/coder/coder/v2/cli/gitauth" "github.com/coder/coder/v2/coderd/database/dbtime" "github.com/coder/coder/v2/codersdk" @@ -797,7 +798,12 @@ func (a *agent) run() (retErr error) { return xerrors.Errorf("failed to get resources monitoring configuration: %w", err) } - resourcesmonitor := resourcesmonitor.NewResourcesMonitor(logger, clk, config, aAPI) + resourcesFetcher, err := clistat.New() + if err != nil { + return xerrors.Errorf("failed to create resources fetcher: %w", err) + } + + resourcesmonitor := resourcesmonitor.NewResourcesMonitor(logger, clk, config, resourcesFetcher, aAPI) return resourcesmonitor.Start(ctx) }) diff --git a/agent/proto/resourcesmonitor/queue_test.go b/agent/proto/resourcesmonitor/queue_test.go index 320082723e66d..a3a8fbc0d0a3a 100644 --- a/agent/proto/resourcesmonitor/queue_test.go +++ b/agent/proto/resourcesmonitor/queue_test.go @@ -3,6 +3,8 @@ package resourcesmonitor_test import ( "testing" + "github.com/stretchr/testify/require" + "github.com/coder/coder/v2/agent/proto/resourcesmonitor" ) @@ -76,27 +78,15 @@ func TestResourceMonitorQueue(t *testing.T) { }, }) } - if tt.pushCount < 20 && queue.IsFull() { - t.Errorf("expected %v, got %v", false, queue.IsFull()) - } - if tt.pushCount >= 20 && len(queue.Items()) != 20 { - t.Errorf("expected %v, got %v", 20, tt.pushCount) - } - if got := queue.Items(); !equal(got, tt.expected) { - t.Errorf("expected %v, got %v", tt.expected, got) + + if tt.pushCount < 20 { + require.False(t, queue.IsFull()) + } else { + require.True(t, queue.IsFull()) + require.Equal(t, 20, len(queue.Items())) } - }) - } -} -func equal(a, b []resourcesmonitor.Datapoint) bool { - if len(a) != len(b) { - return false - } - for i := range a { - if a[i].Memory.Total != b[i].Memory.Total || a[i].Memory.Used != b[i].Memory.Used { - return false - } + require.EqualValues(t, tt.expected, queue.Items()) + }) } - return true } diff --git a/agent/proto/resourcesmonitor/resources_monitor.go b/agent/proto/resourcesmonitor/resources_monitor.go index 3c3db35233a67..e2f1999697ed0 100644 --- a/agent/proto/resourcesmonitor/resources_monitor.go +++ b/agent/proto/resourcesmonitor/resources_monitor.go @@ -16,16 +16,20 @@ type monitor struct { logger slog.Logger clock quartz.Clock config *proto.GetResourcesMonitoringConfigurationResponse + resourcesFetcher *clistat.Statter datapointsPusher datapointsPusher + queue *Queue } //nolint:revive -func NewResourcesMonitor(logger slog.Logger, clock quartz.Clock, config *proto.GetResourcesMonitoringConfigurationResponse, datapointsPusher datapointsPusher) *monitor { +func NewResourcesMonitor(logger slog.Logger, clock quartz.Clock, config *proto.GetResourcesMonitoringConfigurationResponse, resourcesFetcher *clistat.Statter, datapointsPusher datapointsPusher) *monitor { return &monitor{ logger: logger, clock: clock, config: config, + resourcesFetcher: resourcesFetcher, datapointsPusher: datapointsPusher, + queue: NewQueue(int(config.Config.NumDatapoints)), } } @@ -39,15 +43,8 @@ func (m *monitor) Start(ctx context.Context) error { return nil } - resourcesFetcher, err := clistat.New() - if err != nil { - return xerrors.Errorf("failed to create resources fetcher: %w", err) - } - - datapointsQueue := NewQueue(int(m.config.Config.NumDatapoints)) - m.clock.TickerFunc(ctx, time.Duration(m.config.Config.CollectionIntervalSeconds*int32(time.Second)), func() error { - memTotal, memUsed, err := m.fetchResourceMonitoredMemory(resourcesFetcher) + memTotal, memUsed, err := m.fetchResourceMonitoredMemory() if err != nil { m.logger.Error(ctx, "failed to fetch memory", slog.Error(err)) return nil @@ -55,7 +52,7 @@ func (m *monitor) Start(ctx context.Context) error { volumes := make([]*VolumeDatapoint, 0, len(m.config.MonitoredVolumes)) for _, volume := range m.config.MonitoredVolumes { - volTotal, volUsed, err := m.fetchResourceMonitoredVolume(resourcesFetcher, volume) + volTotal, volUsed, err := m.fetchResourceMonitoredVolume(volume) if err != nil { m.logger.Error(ctx, "failed to fetch volume", slog.Error(err)) continue @@ -68,7 +65,7 @@ func (m *monitor) Start(ctx context.Context) error { }) } - datapointsQueue.Push(Datapoint{ + m.queue.Push(Datapoint{ Memory: &MemoryDatapoint{ Total: memTotal, Used: memUsed, @@ -76,11 +73,14 @@ func (m *monitor) Start(ctx context.Context) error { Volumes: volumes, }) - if datapointsQueue.IsFull() { + if m.queue.IsFull() { _, err = m.datapointsPusher.PushResourcesMonitoringUsage(ctx, &proto.PushResourcesMonitoringUsageRequest{ - Datapoints: datapointsQueue.ItemsAsProto(), + Datapoints: m.queue.ItemsAsProto(), }) if err != nil { + // We don't want to stop the monitoring if we fail to push the datapoints + // to the server. We just log the error and continue. + // The queue will anyway remove the oldest datapoint and add the new one. m.logger.Error(ctx, "failed to push resources monitoring usage", slog.Error(err)) } } @@ -91,8 +91,8 @@ func (m *monitor) Start(ctx context.Context) error { return nil } -func (m *monitor) fetchResourceMonitoredMemory(fetcher *clistat.Statter) (total int64, used int64, err error) { - mem, err := fetcher.HostMemory(clistat.PrefixMebi) +func (m *monitor) fetchResourceMonitoredMemory() (total int64, used int64, err error) { + mem, err := m.resourcesFetcher.HostMemory(clistat.PrefixMebi) if err != nil { return 0, 0, err } @@ -108,8 +108,8 @@ func (m *monitor) fetchResourceMonitoredMemory(fetcher *clistat.Statter) (total return memTotal, memUsed, nil } -func (m *monitor) fetchResourceMonitoredVolume(fetcher *clistat.Statter, volume string) (total int64, used int64, err error) { - vol, err := fetcher.Disk(clistat.PrefixMebi, volume) +func (m *monitor) fetchResourceMonitoredVolume(volume string) (total int64, used int64, err error) { + vol, err := m.resourcesFetcher.Disk(clistat.PrefixMebi, volume) if err != nil { return 0, 0, err } diff --git a/agent/proto/resourcesmonitor/resources_monitor_test.go b/agent/proto/resourcesmonitor/resources_monitor_test.go index 33447ed1199f2..c703519bbdf2c 100644 --- a/agent/proto/resourcesmonitor/resources_monitor_test.go +++ b/agent/proto/resourcesmonitor/resources_monitor_test.go @@ -5,10 +5,13 @@ import ( "os" "testing" + "github.com/stretchr/testify/require" + "cdr.dev/slog" "cdr.dev/slog/sloggers/sloghuman" "github.com/coder/coder/v2/agent/proto" "github.com/coder/coder/v2/agent/proto/resourcesmonitor" + "github.com/coder/coder/v2/cli/clistat" "github.com/coder/quartz" ) @@ -29,7 +32,6 @@ func TestPushResourcesMonitoringWithConfig(t *testing.T) { datapointsPusher func(ctx context.Context, req *proto.PushResourcesMonitoringUsageRequest) (*proto.PushResourcesMonitoringUsageResponse, error) expectedError bool numTicks int - counterCalls int expectedCalls int }{ { @@ -47,7 +49,6 @@ func TestPushResourcesMonitoringWithConfig(t *testing.T) { }, expectedError: false, numTicks: 20, - counterCalls: 0, expectedCalls: 1, }, { @@ -65,7 +66,6 @@ func TestPushResourcesMonitoringWithConfig(t *testing.T) { }, expectedError: false, numTicks: 60, - counterCalls: 0, expectedCalls: 41, }, } @@ -75,14 +75,17 @@ func TestPushResourcesMonitoringWithConfig(t *testing.T) { t.Run(tt.name, func(t *testing.T) { t.Parallel() - clk := quartz.NewMock(t) ctx, cancel := context.WithCancel(context.Background()) defer cancel() - logger := slog.Make(sloghuman.Sink(os.Stdout)) + var ( + logger = slog.Make(sloghuman.Sink(os.Stdout)) + clk = quartz.NewMock(t) + counterCalls = 0 + ) datapointsPusher := func(ctx context.Context, params *proto.PushResourcesMonitoringUsageRequest) (*proto.PushResourcesMonitoringUsageResponse, error) { - tt.counterCalls++ + counterCalls++ return tt.datapointsPusher(ctx, params) } @@ -90,25 +93,24 @@ func TestPushResourcesMonitoringWithConfig(t *testing.T) { PushResourcesMonitoringUsageFunc: datapointsPusher, } - monitor := resourcesmonitor.NewResourcesMonitor(logger, clk, tt.config, pusher) - err := monitor.Start(ctx) - if (err != nil) != tt.expectedError { - t.Errorf("expected error: %v, got: %v", tt.expectedError, err) - } + resourcesFetcher, err := clistat.New() + require.NoError(t, err) + monitor := resourcesmonitor.NewResourcesMonitor(logger, clk, tt.config, resourcesFetcher, pusher) + err = monitor.Start(ctx) if tt.expectedError { + require.Error(t, err) return } + require.NoError(t, err) + for i := 0; i < tt.numTicks; i++ { _, waiter := clk.AdvanceNext() - waiter.Wait(ctx) - } - - if tt.counterCalls != tt.expectedCalls { - t.Errorf("expected call count: %v, got: %v", tt.expectedCalls, tt.counterCalls) + require.NoError(t, waiter.Wait(ctx)) } + require.Equal(t, tt.expectedCalls, counterCalls) cancel() }) } diff --git a/coderd/agentapi/resources_monitoring.go b/coderd/agentapi/resources_monitoring.go index 359cb3e06241c..c9d390203001e 100644 --- a/coderd/agentapi/resources_monitoring.go +++ b/coderd/agentapi/resources_monitoring.go @@ -5,6 +5,8 @@ import ( "database/sql" "errors" + "golang.org/x/xerrors" + "cdr.dev/slog" "github.com/coder/coder/v2/agent/proto" "github.com/coder/coder/v2/coderd/database" @@ -24,7 +26,7 @@ func (a *ResourcesMonitoringAPI) GetResourcesMonitoringConfiguration(ctx context _, err = a.Database.FetchMemoryResourceMonitorsByAgentID(ctx, agent.ID) if err != nil && !errors.Is(err, sql.ErrNoRows) { - return nil, err + return nil, xerrors.New("failed to fetch memory resource monitors") } volumeMonitors, err := a.Database.FetchVolumesResourceMonitorsByAgentID(ctx, agent.ID) From 18b65e0d953e0de335903c50034251ace55fb38f Mon Sep 17 00:00:00 2001 From: defelmnq Date: Wed, 12 Feb 2025 10:39:51 +0000 Subject: [PATCH 17/32] improve resourcesmonitor struct --- agent/proto/resourcesmonitor/resources_monitor.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/agent/proto/resourcesmonitor/resources_monitor.go b/agent/proto/resourcesmonitor/resources_monitor.go index e2f1999697ed0..d88961841bc9d 100644 --- a/agent/proto/resourcesmonitor/resources_monitor.go +++ b/agent/proto/resourcesmonitor/resources_monitor.go @@ -43,7 +43,7 @@ func (m *monitor) Start(ctx context.Context) error { return nil } - m.clock.TickerFunc(ctx, time.Duration(m.config.Config.CollectionIntervalSeconds*int32(time.Second)), func() error { + m.clock.TickerFunc(ctx, time.Duration(m.config.Config.CollectionIntervalSeconds)*time.Second, func() error { memTotal, memUsed, err := m.fetchResourceMonitoredMemory() if err != nil { m.logger.Error(ctx, "failed to fetch memory", slog.Error(err)) From c95b05a00db7461c073c5fb36fc23c0338d8e048 Mon Sep 17 00:00:00 2001 From: defelmnq Date: Wed, 12 Feb 2025 22:20:13 +0000 Subject: [PATCH 18/32] change proto payload for get resources monitoring config --- agent/proto/agent.pb.go | 573 +++++++++++------- agent/proto/agent.proto | 15 +- .../resourcesmonitor/resources_monitor.go | 42 +- .../resources_monitor_test.go | 16 +- coderd/agentapi/resources_monitoring.go | 37 +- 5 files changed, 428 insertions(+), 255 deletions(-) diff --git a/agent/proto/agent.pb.go b/agent/proto/agent.pb.go index 0107d1ee87109..f60d20765a13c 100644 --- a/agent/proto/agent.pb.go +++ b/agent/proto/agent.pb.go @@ -2347,9 +2347,9 @@ type GetResourcesMonitoringConfigurationResponse struct { sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Enabled bool `protobuf:"varint,1,opt,name=enabled,proto3" json:"enabled,omitempty"` - Config *GetResourcesMonitoringConfigurationResponse_Config `protobuf:"bytes,2,opt,name=config,proto3" json:"config,omitempty"` - MonitoredVolumes []string `protobuf:"bytes,3,rep,name=monitored_volumes,json=monitoredVolumes,proto3" json:"monitored_volumes,omitempty"` + Config *GetResourcesMonitoringConfigurationResponse_Config `protobuf:"bytes,1,opt,name=config,proto3" json:"config,omitempty"` + Memory *GetResourcesMonitoringConfigurationResponse_Memory `protobuf:"bytes,2,opt,name=memory,proto3,oneof" json:"memory,omitempty"` + Volumes []*GetResourcesMonitoringConfigurationResponse_Volume `protobuf:"bytes,3,rep,name=volumes,proto3" json:"volumes,omitempty"` } func (x *GetResourcesMonitoringConfigurationResponse) Reset() { @@ -2384,23 +2384,23 @@ func (*GetResourcesMonitoringConfigurationResponse) Descriptor() ([]byte, []int) return file_agent_proto_agent_proto_rawDescGZIP(), []int{29} } -func (x *GetResourcesMonitoringConfigurationResponse) GetEnabled() bool { +func (x *GetResourcesMonitoringConfigurationResponse) GetConfig() *GetResourcesMonitoringConfigurationResponse_Config { if x != nil { - return x.Enabled + return x.Config } - return false + return nil } -func (x *GetResourcesMonitoringConfigurationResponse) GetConfig() *GetResourcesMonitoringConfigurationResponse_Config { +func (x *GetResourcesMonitoringConfigurationResponse) GetMemory() *GetResourcesMonitoringConfigurationResponse_Memory { if x != nil { - return x.Config + return x.Memory } return nil } -func (x *GetResourcesMonitoringConfigurationResponse) GetMonitoredVolumes() []string { +func (x *GetResourcesMonitoringConfigurationResponse) GetVolumes() []*GetResourcesMonitoringConfigurationResponse_Volume { if x != nil { - return x.MonitoredVolumes + return x.Volumes } return nil } @@ -2939,6 +2939,108 @@ func (x *GetResourcesMonitoringConfigurationResponse_Config) GetCollectionInterv return 0 } +type GetResourcesMonitoringConfigurationResponse_Memory struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Enabled bool `protobuf:"varint,1,opt,name=enabled,proto3" json:"enabled,omitempty"` +} + +func (x *GetResourcesMonitoringConfigurationResponse_Memory) Reset() { + *x = GetResourcesMonitoringConfigurationResponse_Memory{} + if protoimpl.UnsafeEnabled { + mi := &file_agent_proto_agent_proto_msgTypes[41] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetResourcesMonitoringConfigurationResponse_Memory) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetResourcesMonitoringConfigurationResponse_Memory) ProtoMessage() {} + +func (x *GetResourcesMonitoringConfigurationResponse_Memory) ProtoReflect() protoreflect.Message { + mi := &file_agent_proto_agent_proto_msgTypes[41] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetResourcesMonitoringConfigurationResponse_Memory.ProtoReflect.Descriptor instead. +func (*GetResourcesMonitoringConfigurationResponse_Memory) Descriptor() ([]byte, []int) { + return file_agent_proto_agent_proto_rawDescGZIP(), []int{29, 1} +} + +func (x *GetResourcesMonitoringConfigurationResponse_Memory) GetEnabled() bool { + if x != nil { + return x.Enabled + } + return false +} + +type GetResourcesMonitoringConfigurationResponse_Volume struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Enabled bool `protobuf:"varint,1,opt,name=enabled,proto3" json:"enabled,omitempty"` + Path string `protobuf:"bytes,2,opt,name=path,proto3" json:"path,omitempty"` +} + +func (x *GetResourcesMonitoringConfigurationResponse_Volume) Reset() { + *x = GetResourcesMonitoringConfigurationResponse_Volume{} + if protoimpl.UnsafeEnabled { + mi := &file_agent_proto_agent_proto_msgTypes[42] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *GetResourcesMonitoringConfigurationResponse_Volume) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*GetResourcesMonitoringConfigurationResponse_Volume) ProtoMessage() {} + +func (x *GetResourcesMonitoringConfigurationResponse_Volume) ProtoReflect() protoreflect.Message { + mi := &file_agent_proto_agent_proto_msgTypes[42] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use GetResourcesMonitoringConfigurationResponse_Volume.ProtoReflect.Descriptor instead. +func (*GetResourcesMonitoringConfigurationResponse_Volume) Descriptor() ([]byte, []int) { + return file_agent_proto_agent_proto_rawDescGZIP(), []int{29, 2} +} + +func (x *GetResourcesMonitoringConfigurationResponse_Volume) GetEnabled() bool { + if x != nil { + return x.Enabled + } + return false +} + +func (x *GetResourcesMonitoringConfigurationResponse_Volume) GetPath() string { + if x != nil { + return x.Path + } + return "" +} + type PushResourcesMonitoringUsageRequest_Datapoint struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -2952,7 +3054,7 @@ type PushResourcesMonitoringUsageRequest_Datapoint struct { func (x *PushResourcesMonitoringUsageRequest_Datapoint) Reset() { *x = PushResourcesMonitoringUsageRequest_Datapoint{} if protoimpl.UnsafeEnabled { - mi := &file_agent_proto_agent_proto_msgTypes[41] + mi := &file_agent_proto_agent_proto_msgTypes[43] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -2965,7 +3067,7 @@ func (x *PushResourcesMonitoringUsageRequest_Datapoint) String() string { func (*PushResourcesMonitoringUsageRequest_Datapoint) ProtoMessage() {} func (x *PushResourcesMonitoringUsageRequest_Datapoint) ProtoReflect() protoreflect.Message { - mi := &file_agent_proto_agent_proto_msgTypes[41] + mi := &file_agent_proto_agent_proto_msgTypes[43] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3014,7 +3116,7 @@ type PushResourcesMonitoringUsageRequest_Datapoint_MemoryUsage struct { func (x *PushResourcesMonitoringUsageRequest_Datapoint_MemoryUsage) Reset() { *x = PushResourcesMonitoringUsageRequest_Datapoint_MemoryUsage{} if protoimpl.UnsafeEnabled { - mi := &file_agent_proto_agent_proto_msgTypes[42] + mi := &file_agent_proto_agent_proto_msgTypes[44] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3027,7 +3129,7 @@ func (x *PushResourcesMonitoringUsageRequest_Datapoint_MemoryUsage) String() str func (*PushResourcesMonitoringUsageRequest_Datapoint_MemoryUsage) ProtoMessage() {} func (x *PushResourcesMonitoringUsageRequest_Datapoint_MemoryUsage) ProtoReflect() protoreflect.Message { - mi := &file_agent_proto_agent_proto_msgTypes[42] + mi := &file_agent_proto_agent_proto_msgTypes[44] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3070,7 +3172,7 @@ type PushResourcesMonitoringUsageRequest_Datapoint_VolumeUsage struct { func (x *PushResourcesMonitoringUsageRequest_Datapoint_VolumeUsage) Reset() { *x = PushResourcesMonitoringUsageRequest_Datapoint_VolumeUsage{} if protoimpl.UnsafeEnabled { - mi := &file_agent_proto_agent_proto_msgTypes[43] + mi := &file_agent_proto_agent_proto_msgTypes[45] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3083,7 +3185,7 @@ func (x *PushResourcesMonitoringUsageRequest_Datapoint_VolumeUsage) String() str func (*PushResourcesMonitoringUsageRequest_Datapoint_VolumeUsage) ProtoMessage() {} func (x *PushResourcesMonitoringUsageRequest_Datapoint_VolumeUsage) ProtoReflect() protoreflect.Message { - mi := &file_agent_proto_agent_proto_msgTypes[43] + mi := &file_agent_proto_agent_proto_msgTypes[45] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3517,155 +3619,169 @@ var file_agent_proto_agent_proto_rawDesc = []byte{ 0x4e, 0x10, 0x03, 0x22, 0x2c, 0x0a, 0x2a, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x22, 0xc1, 0x02, 0x0a, 0x2b, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x74, 0x22, 0xa0, 0x04, 0x0a, 0x2b, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x5a, 0x0a, 0x06, 0x63, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x42, 0x2e, 0x63, 0x6f, - 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x47, 0x65, 0x74, - 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, - 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, - 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x2b, 0x0a, 0x11, 0x6d, 0x6f, 0x6e, 0x69, 0x74, - 0x6f, 0x72, 0x65, 0x64, 0x5f, 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, - 0x28, 0x09, 0x52, 0x10, 0x6d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x65, 0x64, 0x56, 0x6f, 0x6c, - 0x75, 0x6d, 0x65, 0x73, 0x1a, 0x6f, 0x0a, 0x06, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x25, - 0x0a, 0x0e, 0x6e, 0x75, 0x6d, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, 0x6e, 0x75, 0x6d, 0x44, 0x61, 0x74, 0x61, 0x70, - 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x12, 0x3e, 0x0a, 0x1b, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x5f, 0x73, 0x65, 0x63, - 0x6f, 0x6e, 0x64, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x19, 0x63, 0x6f, 0x6c, 0x6c, - 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x53, 0x65, - 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x22, 0xa3, 0x04, 0x0a, 0x23, 0x50, 0x75, 0x73, 0x68, 0x52, 0x65, + 0x65, 0x12, 0x5a, 0x0a, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x42, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, + 0x76, 0x32, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x4d, + 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, + 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x43, + 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x52, 0x06, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x5f, 0x0a, + 0x06, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x42, 0x2e, + 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x47, + 0x65, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x4d, 0x6f, 0x6e, 0x69, 0x74, + 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, + 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x4d, 0x65, 0x6d, 0x6f, 0x72, + 0x79, 0x48, 0x00, 0x52, 0x06, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x88, 0x01, 0x01, 0x12, 0x5c, + 0x0a, 0x07, 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, + 0x42, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, + 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x4d, 0x6f, 0x6e, + 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2e, 0x56, 0x6f, 0x6c, + 0x75, 0x6d, 0x65, 0x52, 0x07, 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x73, 0x1a, 0x6f, 0x0a, 0x06, + 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x12, 0x25, 0x0a, 0x0e, 0x6e, 0x75, 0x6d, 0x5f, 0x64, 0x61, + 0x74, 0x61, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0d, + 0x6e, 0x75, 0x6d, 0x44, 0x61, 0x74, 0x61, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x12, 0x3e, 0x0a, + 0x1b, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x6e, 0x74, 0x65, + 0x72, 0x76, 0x61, 0x6c, 0x5f, 0x73, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x05, 0x52, 0x19, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x6e, + 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x53, 0x65, 0x63, 0x6f, 0x6e, 0x64, 0x73, 0x1a, 0x22, 0x0a, + 0x06, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, + 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, + 0x64, 0x1a, 0x36, 0x0a, 0x06, 0x56, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x65, + 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, + 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x6d, 0x65, + 0x6d, 0x6f, 0x72, 0x79, 0x22, 0xa3, 0x04, 0x0a, 0x23, 0x50, 0x75, 0x73, 0x68, 0x52, 0x65, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, + 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x5d, 0x0a, 0x0a, + 0x64, 0x61, 0x74, 0x61, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, + 0x32, 0x3d, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, + 0x32, 0x2e, 0x50, 0x75, 0x73, 0x68, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x4d, + 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, + 0x0a, 0x64, 0x61, 0x74, 0x61, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x1a, 0x9c, 0x03, 0x0a, 0x09, + 0x44, 0x61, 0x74, 0x61, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x3d, 0x0a, 0x0c, 0x63, 0x6f, 0x6c, + 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0b, 0x63, 0x6f, 0x6c, + 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x61, 0x0a, 0x06, 0x6d, 0x65, 0x6d, 0x6f, + 0x72, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x49, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, + 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x50, 0x75, 0x73, 0x68, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, - 0x67, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x5d, 0x0a, - 0x0a, 0x64, 0x61, 0x74, 0x61, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x3d, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, - 0x76, 0x32, 0x2e, 0x50, 0x75, 0x73, 0x68, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, - 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x70, 0x6f, 0x69, 0x6e, 0x74, - 0x52, 0x0a, 0x64, 0x61, 0x74, 0x61, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x1a, 0x9c, 0x03, 0x0a, - 0x09, 0x44, 0x61, 0x74, 0x61, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x3d, 0x0a, 0x0c, 0x63, 0x6f, - 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0b, 0x63, 0x6f, - 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x61, 0x0a, 0x06, 0x6d, 0x65, 0x6d, - 0x6f, 0x72, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x49, 0x2e, 0x63, 0x6f, 0x64, 0x65, - 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x50, 0x75, 0x73, 0x68, 0x52, - 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, - 0x6e, 0x67, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x44, - 0x61, 0x74, 0x61, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x2e, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x55, - 0x73, 0x61, 0x67, 0x65, 0x52, 0x06, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x12, 0x63, 0x0a, 0x07, - 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x49, 0x2e, - 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x50, - 0x75, 0x73, 0x68, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x4d, 0x6f, 0x6e, 0x69, - 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x2e, 0x56, 0x6f, 0x6c, - 0x75, 0x6d, 0x65, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x07, 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, - 0x73, 0x1a, 0x37, 0x0a, 0x0b, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x55, 0x73, 0x61, 0x67, 0x65, - 0x12, 0x12, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, - 0x75, 0x73, 0x65, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x1a, 0x4f, 0x0a, 0x0b, 0x56, 0x6f, - 0x6c, 0x75, 0x6d, 0x65, 0x55, 0x73, 0x61, 0x67, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x76, 0x6f, 0x6c, - 0x75, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x76, 0x6f, 0x6c, 0x75, 0x6d, - 0x65, 0x12, 0x12, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, - 0x04, 0x75, 0x73, 0x65, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x22, 0x26, 0x0a, 0x24, 0x50, - 0x75, 0x73, 0x68, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x4d, 0x6f, 0x6e, 0x69, - 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x2a, 0x63, 0x0a, 0x09, 0x41, 0x70, 0x70, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, - 0x12, 0x1a, 0x0a, 0x16, 0x41, 0x50, 0x50, 0x5f, 0x48, 0x45, 0x41, 0x4c, 0x54, 0x48, 0x5f, 0x55, - 0x4e, 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0c, 0x0a, 0x08, - 0x44, 0x49, 0x53, 0x41, 0x42, 0x4c, 0x45, 0x44, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x49, 0x4e, - 0x49, 0x54, 0x49, 0x41, 0x4c, 0x49, 0x5a, 0x49, 0x4e, 0x47, 0x10, 0x02, 0x12, 0x0b, 0x0a, 0x07, - 0x48, 0x45, 0x41, 0x4c, 0x54, 0x48, 0x59, 0x10, 0x03, 0x12, 0x0d, 0x0a, 0x09, 0x55, 0x4e, 0x48, - 0x45, 0x41, 0x4c, 0x54, 0x48, 0x59, 0x10, 0x04, 0x32, 0x9c, 0x0a, 0x0a, 0x05, 0x41, 0x67, 0x65, - 0x6e, 0x74, 0x12, 0x4b, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x4d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, - 0x74, 0x12, 0x22, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, - 0x76, 0x32, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, - 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x4d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x12, - 0x5a, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x42, 0x61, 0x6e, - 0x6e, 0x65, 0x72, 0x12, 0x27, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, - 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x42, - 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x63, - 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x53, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x42, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x12, 0x56, 0x0a, 0x0b, 0x55, - 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x22, 0x2e, 0x63, 0x6f, 0x64, - 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x55, 0x70, 0x64, 0x61, - 0x74, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, - 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, - 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x54, 0x0a, 0x0f, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x66, - 0x65, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x12, 0x26, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, - 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4c, 0x69, - 0x66, 0x65, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, - 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, - 0x4c, 0x69, 0x66, 0x65, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x12, 0x72, 0x0a, 0x15, 0x42, 0x61, 0x74, - 0x63, 0x68, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x70, 0x70, 0x48, 0x65, 0x61, 0x6c, 0x74, - 0x68, 0x73, 0x12, 0x2b, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, - 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, - 0x70, 0x70, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x2c, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, - 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x70, 0x70, 0x48, - 0x65, 0x61, 0x6c, 0x74, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4e, 0x0a, - 0x0d, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x12, 0x24, + 0x67, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x44, 0x61, + 0x74, 0x61, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x2e, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x55, 0x73, + 0x61, 0x67, 0x65, 0x52, 0x06, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x12, 0x63, 0x0a, 0x07, 0x76, + 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x49, 0x2e, 0x63, + 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x50, 0x75, + 0x73, 0x68, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x4d, 0x6f, 0x6e, 0x69, 0x74, + 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x2e, 0x56, 0x6f, 0x6c, 0x75, + 0x6d, 0x65, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x07, 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x73, + 0x1a, 0x37, 0x0a, 0x0b, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x55, 0x73, 0x61, 0x67, 0x65, 0x12, + 0x12, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x75, + 0x73, 0x65, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x1a, 0x4f, 0x0a, 0x0b, 0x56, 0x6f, 0x6c, + 0x75, 0x6d, 0x65, 0x55, 0x73, 0x61, 0x67, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x76, 0x6f, 0x6c, 0x75, + 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, + 0x12, 0x12, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, + 0x75, 0x73, 0x65, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x22, 0x26, 0x0a, 0x24, 0x50, 0x75, + 0x73, 0x68, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x4d, 0x6f, 0x6e, 0x69, 0x74, + 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x2a, 0x63, 0x0a, 0x09, 0x41, 0x70, 0x70, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x12, + 0x1a, 0x0a, 0x16, 0x41, 0x50, 0x50, 0x5f, 0x48, 0x45, 0x41, 0x4c, 0x54, 0x48, 0x5f, 0x55, 0x4e, + 0x53, 0x50, 0x45, 0x43, 0x49, 0x46, 0x49, 0x45, 0x44, 0x10, 0x00, 0x12, 0x0c, 0x0a, 0x08, 0x44, + 0x49, 0x53, 0x41, 0x42, 0x4c, 0x45, 0x44, 0x10, 0x01, 0x12, 0x10, 0x0a, 0x0c, 0x49, 0x4e, 0x49, + 0x54, 0x49, 0x41, 0x4c, 0x49, 0x5a, 0x49, 0x4e, 0x47, 0x10, 0x02, 0x12, 0x0b, 0x0a, 0x07, 0x48, + 0x45, 0x41, 0x4c, 0x54, 0x48, 0x59, 0x10, 0x03, 0x12, 0x0d, 0x0a, 0x09, 0x55, 0x4e, 0x48, 0x45, + 0x41, 0x4c, 0x54, 0x48, 0x59, 0x10, 0x04, 0x32, 0x9c, 0x0a, 0x0a, 0x05, 0x41, 0x67, 0x65, 0x6e, + 0x74, 0x12, 0x4b, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x4d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, + 0x12, 0x22, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, + 0x32, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, + 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x4d, 0x61, 0x6e, 0x69, 0x66, 0x65, 0x73, 0x74, 0x12, 0x5a, + 0x0a, 0x10, 0x47, 0x65, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x42, 0x61, 0x6e, 0x6e, + 0x65, 0x72, 0x12, 0x27, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, + 0x2e, 0x76, 0x32, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x42, 0x61, + 0x6e, 0x6e, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, 0x63, 0x6f, + 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x53, 0x65, 0x72, + 0x76, 0x69, 0x63, 0x65, 0x42, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x12, 0x56, 0x0a, 0x0b, 0x55, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x12, 0x22, 0x2e, 0x63, 0x6f, 0x64, 0x65, + 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x23, 0x2e, + 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x55, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x74, 0x61, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x54, 0x0a, 0x0f, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x66, 0x65, + 0x63, 0x79, 0x63, 0x6c, 0x65, 0x12, 0x26, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, + 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4c, 0x69, 0x66, + 0x65, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, + 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x4c, + 0x69, 0x66, 0x65, 0x63, 0x79, 0x63, 0x6c, 0x65, 0x12, 0x72, 0x0a, 0x15, 0x42, 0x61, 0x74, 0x63, + 0x68, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x70, 0x70, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, + 0x73, 0x12, 0x2b, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, + 0x76, 0x32, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x70, + 0x70, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2c, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, - 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, - 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x12, 0x6e, 0x0a, - 0x13, 0x42, 0x61, 0x74, 0x63, 0x68, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x74, 0x61, - 0x64, 0x61, 0x74, 0x61, 0x12, 0x2a, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, - 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x55, 0x70, 0x64, 0x61, 0x74, - 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x2b, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, - 0x32, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x74, - 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x62, 0x0a, - 0x0f, 0x42, 0x61, 0x74, 0x63, 0x68, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4c, 0x6f, 0x67, 0x73, - 0x12, 0x26, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, - 0x32, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4c, 0x6f, 0x67, - 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, - 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x43, - 0x72, 0x65, 0x61, 0x74, 0x65, 0x4c, 0x6f, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, - 0x65, 0x12, 0x77, 0x0a, 0x16, 0x47, 0x65, 0x74, 0x41, 0x6e, 0x6e, 0x6f, 0x75, 0x6e, 0x63, 0x65, - 0x6d, 0x65, 0x6e, 0x74, 0x42, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x73, 0x12, 0x2d, 0x2e, 0x63, 0x6f, - 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x47, 0x65, 0x74, - 0x41, 0x6e, 0x6e, 0x6f, 0x75, 0x6e, 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x42, 0x61, 0x6e, 0x6e, - 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x63, 0x6f, 0x64, + 0x42, 0x61, 0x74, 0x63, 0x68, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x70, 0x70, 0x48, 0x65, + 0x61, 0x6c, 0x74, 0x68, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4e, 0x0a, 0x0d, + 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x12, 0x24, 0x2e, + 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x55, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x53, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, + 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x12, 0x6e, 0x0a, 0x13, + 0x42, 0x61, 0x74, 0x63, 0x68, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x74, 0x61, 0x64, + 0x61, 0x74, 0x61, 0x12, 0x2a, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, + 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, + 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x2b, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, + 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x74, 0x61, + 0x64, 0x61, 0x74, 0x61, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x62, 0x0a, 0x0f, + 0x42, 0x61, 0x74, 0x63, 0x68, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4c, 0x6f, 0x67, 0x73, 0x12, + 0x26, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, + 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x4c, 0x6f, 0x67, 0x73, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x27, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, + 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x42, 0x61, 0x74, 0x63, 0x68, 0x43, 0x72, + 0x65, 0x61, 0x74, 0x65, 0x4c, 0x6f, 0x67, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x77, 0x0a, 0x16, 0x47, 0x65, 0x74, 0x41, 0x6e, 0x6e, 0x6f, 0x75, 0x6e, 0x63, 0x65, 0x6d, + 0x65, 0x6e, 0x74, 0x42, 0x61, 0x6e, 0x6e, 0x65, 0x72, 0x73, 0x12, 0x2d, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x6e, 0x6e, 0x6f, 0x75, 0x6e, 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x42, 0x61, 0x6e, 0x6e, 0x65, - 0x72, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x7e, 0x0a, 0x0f, 0x53, 0x63, - 0x72, 0x69, 0x70, 0x74, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x12, 0x34, 0x2e, - 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x57, - 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x53, 0x63, 0x72, - 0x69, 0x70, 0x74, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, - 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x41, 0x67, - 0x65, 0x6e, 0x74, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, - 0x65, 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x9e, 0x01, 0x0a, 0x23, 0x47, + 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x2e, 0x2e, 0x63, 0x6f, 0x64, 0x65, + 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x6e, + 0x6e, 0x6f, 0x75, 0x6e, 0x63, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x42, 0x61, 0x6e, 0x6e, 0x65, 0x72, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x7e, 0x0a, 0x0f, 0x53, 0x63, 0x72, + 0x69, 0x70, 0x74, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x12, 0x34, 0x2e, 0x63, + 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x57, 0x6f, + 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x41, 0x67, 0x65, 0x6e, 0x74, 0x53, 0x63, 0x72, 0x69, + 0x70, 0x74, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x35, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, + 0x2e, 0x76, 0x32, 0x2e, 0x57, 0x6f, 0x72, 0x6b, 0x73, 0x70, 0x61, 0x63, 0x65, 0x41, 0x67, 0x65, + 0x6e, 0x74, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x43, 0x6f, 0x6d, 0x70, 0x6c, 0x65, 0x74, 0x65, + 0x64, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x9e, 0x01, 0x0a, 0x23, 0x47, 0x65, + 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, + 0x72, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x12, 0x3a, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, + 0x76, 0x32, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x4d, + 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, + 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3b, 0x2e, + 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x12, 0x3a, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, - 0x2e, 0x76, 0x32, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, - 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, - 0x75, 0x72, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x3b, - 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, - 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x4d, 0x6f, 0x6e, 0x69, - 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x89, 0x01, 0x0a, 0x1c, - 0x50, 0x75, 0x73, 0x68, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x4d, 0x6f, 0x6e, - 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x55, 0x73, 0x61, 0x67, 0x65, 0x12, 0x33, 0x2e, 0x63, - 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x50, 0x75, - 0x73, 0x68, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x4d, 0x6f, 0x6e, 0x69, 0x74, - 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x34, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, - 0x76, 0x32, 0x2e, 0x50, 0x75, 0x73, 0x68, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, - 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, - 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x27, 0x5a, 0x25, 0x67, 0x69, 0x74, 0x68, 0x75, - 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2f, 0x63, 0x6f, 0x64, 0x65, - 0x72, 0x2f, 0x76, 0x32, 0x2f, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x89, 0x01, 0x0a, 0x1c, 0x50, + 0x75, 0x73, 0x68, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x4d, 0x6f, 0x6e, 0x69, + 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x55, 0x73, 0x61, 0x67, 0x65, 0x12, 0x33, 0x2e, 0x63, 0x6f, + 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x50, 0x75, 0x73, + 0x68, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, + 0x72, 0x69, 0x6e, 0x67, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x34, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, + 0x32, 0x2e, 0x50, 0x75, 0x73, 0x68, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x4d, + 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x42, 0x27, 0x5a, 0x25, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, + 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2f, 0x63, 0x6f, 0x64, 0x65, 0x72, + 0x2f, 0x76, 0x32, 0x2f, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -3681,7 +3797,7 @@ func file_agent_proto_agent_proto_rawDescGZIP() []byte { } var file_agent_proto_agent_proto_enumTypes = make([]protoimpl.EnumInfo, 9) -var file_agent_proto_agent_proto_msgTypes = make([]protoimpl.MessageInfo, 44) +var file_agent_proto_agent_proto_msgTypes = make([]protoimpl.MessageInfo, 46) var file_agent_proto_agent_proto_goTypes = []interface{}{ (AppHealth)(0), // 0: coder.agent.v2.AppHealth (WorkspaceApp_SharingLevel)(0), // 1: coder.agent.v2.WorkspaceApp.SharingLevel @@ -3733,87 +3849,91 @@ var file_agent_proto_agent_proto_goTypes = []interface{}{ (*Stats_Metric_Label)(nil), // 47: coder.agent.v2.Stats.Metric.Label (*BatchUpdateAppHealthRequest_HealthUpdate)(nil), // 48: coder.agent.v2.BatchUpdateAppHealthRequest.HealthUpdate (*GetResourcesMonitoringConfigurationResponse_Config)(nil), // 49: coder.agent.v2.GetResourcesMonitoringConfigurationResponse.Config - (*PushResourcesMonitoringUsageRequest_Datapoint)(nil), // 50: coder.agent.v2.PushResourcesMonitoringUsageRequest.Datapoint - (*PushResourcesMonitoringUsageRequest_Datapoint_MemoryUsage)(nil), // 51: coder.agent.v2.PushResourcesMonitoringUsageRequest.Datapoint.MemoryUsage - (*PushResourcesMonitoringUsageRequest_Datapoint_VolumeUsage)(nil), // 52: coder.agent.v2.PushResourcesMonitoringUsageRequest.Datapoint.VolumeUsage - (*durationpb.Duration)(nil), // 53: google.protobuf.Duration - (*proto.DERPMap)(nil), // 54: coder.tailnet.v2.DERPMap - (*timestamppb.Timestamp)(nil), // 55: google.protobuf.Timestamp + (*GetResourcesMonitoringConfigurationResponse_Memory)(nil), // 50: coder.agent.v2.GetResourcesMonitoringConfigurationResponse.Memory + (*GetResourcesMonitoringConfigurationResponse_Volume)(nil), // 51: coder.agent.v2.GetResourcesMonitoringConfigurationResponse.Volume + (*PushResourcesMonitoringUsageRequest_Datapoint)(nil), // 52: coder.agent.v2.PushResourcesMonitoringUsageRequest.Datapoint + (*PushResourcesMonitoringUsageRequest_Datapoint_MemoryUsage)(nil), // 53: coder.agent.v2.PushResourcesMonitoringUsageRequest.Datapoint.MemoryUsage + (*PushResourcesMonitoringUsageRequest_Datapoint_VolumeUsage)(nil), // 54: coder.agent.v2.PushResourcesMonitoringUsageRequest.Datapoint.VolumeUsage + (*durationpb.Duration)(nil), // 55: google.protobuf.Duration + (*proto.DERPMap)(nil), // 56: coder.tailnet.v2.DERPMap + (*timestamppb.Timestamp)(nil), // 57: google.protobuf.Timestamp } var file_agent_proto_agent_proto_depIdxs = []int32{ 1, // 0: coder.agent.v2.WorkspaceApp.sharing_level:type_name -> coder.agent.v2.WorkspaceApp.SharingLevel 41, // 1: coder.agent.v2.WorkspaceApp.healthcheck:type_name -> coder.agent.v2.WorkspaceApp.Healthcheck 2, // 2: coder.agent.v2.WorkspaceApp.health:type_name -> coder.agent.v2.WorkspaceApp.Health - 53, // 3: coder.agent.v2.WorkspaceAgentScript.timeout:type_name -> google.protobuf.Duration + 55, // 3: coder.agent.v2.WorkspaceAgentScript.timeout:type_name -> google.protobuf.Duration 42, // 4: coder.agent.v2.WorkspaceAgentMetadata.result:type_name -> coder.agent.v2.WorkspaceAgentMetadata.Result 43, // 5: coder.agent.v2.WorkspaceAgentMetadata.description:type_name -> coder.agent.v2.WorkspaceAgentMetadata.Description 44, // 6: coder.agent.v2.Manifest.environment_variables:type_name -> coder.agent.v2.Manifest.EnvironmentVariablesEntry - 54, // 7: coder.agent.v2.Manifest.derp_map:type_name -> coder.tailnet.v2.DERPMap + 56, // 7: coder.agent.v2.Manifest.derp_map:type_name -> coder.tailnet.v2.DERPMap 10, // 8: coder.agent.v2.Manifest.scripts:type_name -> coder.agent.v2.WorkspaceAgentScript 9, // 9: coder.agent.v2.Manifest.apps:type_name -> coder.agent.v2.WorkspaceApp 43, // 10: coder.agent.v2.Manifest.metadata:type_name -> coder.agent.v2.WorkspaceAgentMetadata.Description 45, // 11: coder.agent.v2.Stats.connections_by_proto:type_name -> coder.agent.v2.Stats.ConnectionsByProtoEntry 46, // 12: coder.agent.v2.Stats.metrics:type_name -> coder.agent.v2.Stats.Metric 16, // 13: coder.agent.v2.UpdateStatsRequest.stats:type_name -> coder.agent.v2.Stats - 53, // 14: coder.agent.v2.UpdateStatsResponse.report_interval:type_name -> google.protobuf.Duration + 55, // 14: coder.agent.v2.UpdateStatsResponse.report_interval:type_name -> google.protobuf.Duration 4, // 15: coder.agent.v2.Lifecycle.state:type_name -> coder.agent.v2.Lifecycle.State - 55, // 16: coder.agent.v2.Lifecycle.changed_at:type_name -> google.protobuf.Timestamp + 57, // 16: coder.agent.v2.Lifecycle.changed_at:type_name -> google.protobuf.Timestamp 19, // 17: coder.agent.v2.UpdateLifecycleRequest.lifecycle:type_name -> coder.agent.v2.Lifecycle 48, // 18: coder.agent.v2.BatchUpdateAppHealthRequest.updates:type_name -> coder.agent.v2.BatchUpdateAppHealthRequest.HealthUpdate 5, // 19: coder.agent.v2.Startup.subsystems:type_name -> coder.agent.v2.Startup.Subsystem 23, // 20: coder.agent.v2.UpdateStartupRequest.startup:type_name -> coder.agent.v2.Startup 42, // 21: coder.agent.v2.Metadata.result:type_name -> coder.agent.v2.WorkspaceAgentMetadata.Result 25, // 22: coder.agent.v2.BatchUpdateMetadataRequest.metadata:type_name -> coder.agent.v2.Metadata - 55, // 23: coder.agent.v2.Log.created_at:type_name -> google.protobuf.Timestamp + 57, // 23: coder.agent.v2.Log.created_at:type_name -> google.protobuf.Timestamp 6, // 24: coder.agent.v2.Log.level:type_name -> coder.agent.v2.Log.Level 28, // 25: coder.agent.v2.BatchCreateLogsRequest.logs:type_name -> coder.agent.v2.Log 33, // 26: coder.agent.v2.GetAnnouncementBannersResponse.announcement_banners:type_name -> coder.agent.v2.BannerConfig 36, // 27: coder.agent.v2.WorkspaceAgentScriptCompletedRequest.timing:type_name -> coder.agent.v2.Timing - 55, // 28: coder.agent.v2.Timing.start:type_name -> google.protobuf.Timestamp - 55, // 29: coder.agent.v2.Timing.end:type_name -> google.protobuf.Timestamp + 57, // 28: coder.agent.v2.Timing.start:type_name -> google.protobuf.Timestamp + 57, // 29: coder.agent.v2.Timing.end:type_name -> google.protobuf.Timestamp 7, // 30: coder.agent.v2.Timing.stage:type_name -> coder.agent.v2.Timing.Stage 8, // 31: coder.agent.v2.Timing.status:type_name -> coder.agent.v2.Timing.Status 49, // 32: coder.agent.v2.GetResourcesMonitoringConfigurationResponse.config:type_name -> coder.agent.v2.GetResourcesMonitoringConfigurationResponse.Config - 50, // 33: coder.agent.v2.PushResourcesMonitoringUsageRequest.datapoints:type_name -> coder.agent.v2.PushResourcesMonitoringUsageRequest.Datapoint - 53, // 34: coder.agent.v2.WorkspaceApp.Healthcheck.interval:type_name -> google.protobuf.Duration - 55, // 35: coder.agent.v2.WorkspaceAgentMetadata.Result.collected_at:type_name -> google.protobuf.Timestamp - 53, // 36: coder.agent.v2.WorkspaceAgentMetadata.Description.interval:type_name -> google.protobuf.Duration - 53, // 37: coder.agent.v2.WorkspaceAgentMetadata.Description.timeout:type_name -> google.protobuf.Duration - 3, // 38: coder.agent.v2.Stats.Metric.type:type_name -> coder.agent.v2.Stats.Metric.Type - 47, // 39: coder.agent.v2.Stats.Metric.labels:type_name -> coder.agent.v2.Stats.Metric.Label - 0, // 40: coder.agent.v2.BatchUpdateAppHealthRequest.HealthUpdate.health:type_name -> coder.agent.v2.AppHealth - 55, // 41: coder.agent.v2.PushResourcesMonitoringUsageRequest.Datapoint.collected_at:type_name -> google.protobuf.Timestamp - 51, // 42: coder.agent.v2.PushResourcesMonitoringUsageRequest.Datapoint.memory:type_name -> coder.agent.v2.PushResourcesMonitoringUsageRequest.Datapoint.MemoryUsage - 52, // 43: coder.agent.v2.PushResourcesMonitoringUsageRequest.Datapoint.volumes:type_name -> coder.agent.v2.PushResourcesMonitoringUsageRequest.Datapoint.VolumeUsage - 13, // 44: coder.agent.v2.Agent.GetManifest:input_type -> coder.agent.v2.GetManifestRequest - 15, // 45: coder.agent.v2.Agent.GetServiceBanner:input_type -> coder.agent.v2.GetServiceBannerRequest - 17, // 46: coder.agent.v2.Agent.UpdateStats:input_type -> coder.agent.v2.UpdateStatsRequest - 20, // 47: coder.agent.v2.Agent.UpdateLifecycle:input_type -> coder.agent.v2.UpdateLifecycleRequest - 21, // 48: coder.agent.v2.Agent.BatchUpdateAppHealths:input_type -> coder.agent.v2.BatchUpdateAppHealthRequest - 24, // 49: coder.agent.v2.Agent.UpdateStartup:input_type -> coder.agent.v2.UpdateStartupRequest - 26, // 50: coder.agent.v2.Agent.BatchUpdateMetadata:input_type -> coder.agent.v2.BatchUpdateMetadataRequest - 29, // 51: coder.agent.v2.Agent.BatchCreateLogs:input_type -> coder.agent.v2.BatchCreateLogsRequest - 31, // 52: coder.agent.v2.Agent.GetAnnouncementBanners:input_type -> coder.agent.v2.GetAnnouncementBannersRequest - 34, // 53: coder.agent.v2.Agent.ScriptCompleted:input_type -> coder.agent.v2.WorkspaceAgentScriptCompletedRequest - 37, // 54: coder.agent.v2.Agent.GetResourcesMonitoringConfiguration:input_type -> coder.agent.v2.GetResourcesMonitoringConfigurationRequest - 39, // 55: coder.agent.v2.Agent.PushResourcesMonitoringUsage:input_type -> coder.agent.v2.PushResourcesMonitoringUsageRequest - 12, // 56: coder.agent.v2.Agent.GetManifest:output_type -> coder.agent.v2.Manifest - 14, // 57: coder.agent.v2.Agent.GetServiceBanner:output_type -> coder.agent.v2.ServiceBanner - 18, // 58: coder.agent.v2.Agent.UpdateStats:output_type -> coder.agent.v2.UpdateStatsResponse - 19, // 59: coder.agent.v2.Agent.UpdateLifecycle:output_type -> coder.agent.v2.Lifecycle - 22, // 60: coder.agent.v2.Agent.BatchUpdateAppHealths:output_type -> coder.agent.v2.BatchUpdateAppHealthResponse - 23, // 61: coder.agent.v2.Agent.UpdateStartup:output_type -> coder.agent.v2.Startup - 27, // 62: coder.agent.v2.Agent.BatchUpdateMetadata:output_type -> coder.agent.v2.BatchUpdateMetadataResponse - 30, // 63: coder.agent.v2.Agent.BatchCreateLogs:output_type -> coder.agent.v2.BatchCreateLogsResponse - 32, // 64: coder.agent.v2.Agent.GetAnnouncementBanners:output_type -> coder.agent.v2.GetAnnouncementBannersResponse - 35, // 65: coder.agent.v2.Agent.ScriptCompleted:output_type -> coder.agent.v2.WorkspaceAgentScriptCompletedResponse - 38, // 66: coder.agent.v2.Agent.GetResourcesMonitoringConfiguration:output_type -> coder.agent.v2.GetResourcesMonitoringConfigurationResponse - 40, // 67: coder.agent.v2.Agent.PushResourcesMonitoringUsage:output_type -> coder.agent.v2.PushResourcesMonitoringUsageResponse - 56, // [56:68] is the sub-list for method output_type - 44, // [44:56] is the sub-list for method input_type - 44, // [44:44] is the sub-list for extension type_name - 44, // [44:44] is the sub-list for extension extendee - 0, // [0:44] is the sub-list for field type_name + 50, // 33: coder.agent.v2.GetResourcesMonitoringConfigurationResponse.memory:type_name -> coder.agent.v2.GetResourcesMonitoringConfigurationResponse.Memory + 51, // 34: coder.agent.v2.GetResourcesMonitoringConfigurationResponse.volumes:type_name -> coder.agent.v2.GetResourcesMonitoringConfigurationResponse.Volume + 52, // 35: coder.agent.v2.PushResourcesMonitoringUsageRequest.datapoints:type_name -> coder.agent.v2.PushResourcesMonitoringUsageRequest.Datapoint + 55, // 36: coder.agent.v2.WorkspaceApp.Healthcheck.interval:type_name -> google.protobuf.Duration + 57, // 37: coder.agent.v2.WorkspaceAgentMetadata.Result.collected_at:type_name -> google.protobuf.Timestamp + 55, // 38: coder.agent.v2.WorkspaceAgentMetadata.Description.interval:type_name -> google.protobuf.Duration + 55, // 39: coder.agent.v2.WorkspaceAgentMetadata.Description.timeout:type_name -> google.protobuf.Duration + 3, // 40: coder.agent.v2.Stats.Metric.type:type_name -> coder.agent.v2.Stats.Metric.Type + 47, // 41: coder.agent.v2.Stats.Metric.labels:type_name -> coder.agent.v2.Stats.Metric.Label + 0, // 42: coder.agent.v2.BatchUpdateAppHealthRequest.HealthUpdate.health:type_name -> coder.agent.v2.AppHealth + 57, // 43: coder.agent.v2.PushResourcesMonitoringUsageRequest.Datapoint.collected_at:type_name -> google.protobuf.Timestamp + 53, // 44: coder.agent.v2.PushResourcesMonitoringUsageRequest.Datapoint.memory:type_name -> coder.agent.v2.PushResourcesMonitoringUsageRequest.Datapoint.MemoryUsage + 54, // 45: coder.agent.v2.PushResourcesMonitoringUsageRequest.Datapoint.volumes:type_name -> coder.agent.v2.PushResourcesMonitoringUsageRequest.Datapoint.VolumeUsage + 13, // 46: coder.agent.v2.Agent.GetManifest:input_type -> coder.agent.v2.GetManifestRequest + 15, // 47: coder.agent.v2.Agent.GetServiceBanner:input_type -> coder.agent.v2.GetServiceBannerRequest + 17, // 48: coder.agent.v2.Agent.UpdateStats:input_type -> coder.agent.v2.UpdateStatsRequest + 20, // 49: coder.agent.v2.Agent.UpdateLifecycle:input_type -> coder.agent.v2.UpdateLifecycleRequest + 21, // 50: coder.agent.v2.Agent.BatchUpdateAppHealths:input_type -> coder.agent.v2.BatchUpdateAppHealthRequest + 24, // 51: coder.agent.v2.Agent.UpdateStartup:input_type -> coder.agent.v2.UpdateStartupRequest + 26, // 52: coder.agent.v2.Agent.BatchUpdateMetadata:input_type -> coder.agent.v2.BatchUpdateMetadataRequest + 29, // 53: coder.agent.v2.Agent.BatchCreateLogs:input_type -> coder.agent.v2.BatchCreateLogsRequest + 31, // 54: coder.agent.v2.Agent.GetAnnouncementBanners:input_type -> coder.agent.v2.GetAnnouncementBannersRequest + 34, // 55: coder.agent.v2.Agent.ScriptCompleted:input_type -> coder.agent.v2.WorkspaceAgentScriptCompletedRequest + 37, // 56: coder.agent.v2.Agent.GetResourcesMonitoringConfiguration:input_type -> coder.agent.v2.GetResourcesMonitoringConfigurationRequest + 39, // 57: coder.agent.v2.Agent.PushResourcesMonitoringUsage:input_type -> coder.agent.v2.PushResourcesMonitoringUsageRequest + 12, // 58: coder.agent.v2.Agent.GetManifest:output_type -> coder.agent.v2.Manifest + 14, // 59: coder.agent.v2.Agent.GetServiceBanner:output_type -> coder.agent.v2.ServiceBanner + 18, // 60: coder.agent.v2.Agent.UpdateStats:output_type -> coder.agent.v2.UpdateStatsResponse + 19, // 61: coder.agent.v2.Agent.UpdateLifecycle:output_type -> coder.agent.v2.Lifecycle + 22, // 62: coder.agent.v2.Agent.BatchUpdateAppHealths:output_type -> coder.agent.v2.BatchUpdateAppHealthResponse + 23, // 63: coder.agent.v2.Agent.UpdateStartup:output_type -> coder.agent.v2.Startup + 27, // 64: coder.agent.v2.Agent.BatchUpdateMetadata:output_type -> coder.agent.v2.BatchUpdateMetadataResponse + 30, // 65: coder.agent.v2.Agent.BatchCreateLogs:output_type -> coder.agent.v2.BatchCreateLogsResponse + 32, // 66: coder.agent.v2.Agent.GetAnnouncementBanners:output_type -> coder.agent.v2.GetAnnouncementBannersResponse + 35, // 67: coder.agent.v2.Agent.ScriptCompleted:output_type -> coder.agent.v2.WorkspaceAgentScriptCompletedResponse + 38, // 68: coder.agent.v2.Agent.GetResourcesMonitoringConfiguration:output_type -> coder.agent.v2.GetResourcesMonitoringConfigurationResponse + 40, // 69: coder.agent.v2.Agent.PushResourcesMonitoringUsage:output_type -> coder.agent.v2.PushResourcesMonitoringUsageResponse + 58, // [58:70] is the sub-list for method output_type + 46, // [46:58] is the sub-list for method input_type + 46, // [46:46] is the sub-list for extension type_name + 46, // [46:46] is the sub-list for extension extendee + 0, // [0:46] is the sub-list for field type_name } func init() { file_agent_proto_agent_proto_init() } @@ -4291,7 +4411,7 @@ func file_agent_proto_agent_proto_init() { } } file_agent_proto_agent_proto_msgTypes[41].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PushResourcesMonitoringUsageRequest_Datapoint); i { + switch v := v.(*GetResourcesMonitoringConfigurationResponse_Memory); i { case 0: return &v.state case 1: @@ -4303,7 +4423,7 @@ func file_agent_proto_agent_proto_init() { } } file_agent_proto_agent_proto_msgTypes[42].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*PushResourcesMonitoringUsageRequest_Datapoint_MemoryUsage); i { + switch v := v.(*GetResourcesMonitoringConfigurationResponse_Volume); i { case 0: return &v.state case 1: @@ -4315,6 +4435,30 @@ func file_agent_proto_agent_proto_init() { } } file_agent_proto_agent_proto_msgTypes[43].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PushResourcesMonitoringUsageRequest_Datapoint); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_agent_proto_agent_proto_msgTypes[44].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PushResourcesMonitoringUsageRequest_Datapoint_MemoryUsage); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_agent_proto_agent_proto_msgTypes[45].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*PushResourcesMonitoringUsageRequest_Datapoint_VolumeUsage); i { case 0: return &v.state @@ -4327,13 +4471,14 @@ func file_agent_proto_agent_proto_init() { } } } + file_agent_proto_agent_proto_msgTypes[29].OneofWrappers = []interface{}{} type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_agent_proto_agent_proto_rawDesc, NumEnums: 9, - NumMessages: 44, + NumMessages: 46, NumExtensions: 0, NumServices: 1, }, diff --git a/agent/proto/agent.proto b/agent/proto/agent.proto index 7c02bd4a1cfc5..ce9e676e6f830 100644 --- a/agent/proto/agent.proto +++ b/agent/proto/agent.proto @@ -299,13 +299,22 @@ message GetResourcesMonitoringConfigurationRequest { } message GetResourcesMonitoringConfigurationResponse { - bool enabled = 1; message Config { int32 num_datapoints = 1; int32 collection_interval_seconds = 2; } - Config config = 2; - repeated string monitored_volumes = 3; + Config config = 1; + + message Memory { + bool enabled = 1; + } + optional Memory memory = 2; + + message Volume { + bool enabled = 1; + string path = 2; + } + repeated Volume volumes = 3; } message PushResourcesMonitoringUsageRequest { diff --git a/agent/proto/resourcesmonitor/resources_monitor.go b/agent/proto/resourcesmonitor/resources_monitor.go index d88961841bc9d..5c621886c2213 100644 --- a/agent/proto/resourcesmonitor/resources_monitor.go +++ b/agent/proto/resourcesmonitor/resources_monitor.go @@ -38,43 +38,41 @@ type datapointsPusher interface { } func (m *monitor) Start(ctx context.Context) error { - if !m.config.Enabled { - m.logger.Info(ctx, "resources monitoring is disabled - skipping") - return nil - } - m.clock.TickerFunc(ctx, time.Duration(m.config.Config.CollectionIntervalSeconds)*time.Second, func() error { - memTotal, memUsed, err := m.fetchResourceMonitoredMemory() - if err != nil { - m.logger.Error(ctx, "failed to fetch memory", slog.Error(err)) - return nil + datapoint := Datapoint{ + Volumes: make([]*VolumeDatapoint, 0, len(m.config.Volumes)), + } + + if m.config.Memory != nil && !m.config.Memory.Enabled { + memTotal, memUsed, err := m.fetchResourceMonitoredMemory() + if err != nil { + m.logger.Error(ctx, "failed to fetch memory", slog.Error(err)) + return nil + } + datapoint.Memory = &MemoryDatapoint{ + Total: memTotal, + Used: memUsed, + } } - volumes := make([]*VolumeDatapoint, 0, len(m.config.MonitoredVolumes)) - for _, volume := range m.config.MonitoredVolumes { - volTotal, volUsed, err := m.fetchResourceMonitoredVolume(volume) + for _, volume := range m.config.Volumes { + volTotal, volUsed, err := m.fetchResourceMonitoredVolume(volume.Path) if err != nil { m.logger.Error(ctx, "failed to fetch volume", slog.Error(err)) continue } - volumes = append(volumes, &VolumeDatapoint{ - Path: volume, + datapoint.Volumes = append(datapoint.Volumes, &VolumeDatapoint{ + Path: volume.Path, Total: volTotal, Used: volUsed, }) } - m.queue.Push(Datapoint{ - Memory: &MemoryDatapoint{ - Total: memTotal, - Used: memUsed, - }, - Volumes: volumes, - }) + m.queue.Push(datapoint) if m.queue.IsFull() { - _, err = m.datapointsPusher.PushResourcesMonitoringUsage(ctx, &proto.PushResourcesMonitoringUsageRequest{ + _, err := m.datapointsPusher.PushResourcesMonitoringUsage(ctx, &proto.PushResourcesMonitoringUsageRequest{ Datapoints: m.queue.ItemsAsProto(), }) if err != nil { diff --git a/agent/proto/resourcesmonitor/resources_monitor_test.go b/agent/proto/resourcesmonitor/resources_monitor_test.go index c703519bbdf2c..c3786cf10879a 100644 --- a/agent/proto/resourcesmonitor/resources_monitor_test.go +++ b/agent/proto/resourcesmonitor/resources_monitor_test.go @@ -37,12 +37,16 @@ func TestPushResourcesMonitoringWithConfig(t *testing.T) { { name: "SuccessfulMonitoring", config: &proto.GetResourcesMonitoringConfigurationResponse{ - Enabled: true, Config: &proto.GetResourcesMonitoringConfigurationResponse_Config{ NumDatapoints: 20, CollectionIntervalSeconds: 1, }, - MonitoredVolumes: []string{"/"}, + Volumes: []*proto.GetResourcesMonitoringConfigurationResponse_Volume{ + { + Enabled: true, + Path: "/", + }, + }, }, datapointsPusher: func(_ context.Context, _ *proto.PushResourcesMonitoringUsageRequest) (*proto.PushResourcesMonitoringUsageResponse, error) { return &proto.PushResourcesMonitoringUsageResponse{}, nil @@ -54,12 +58,16 @@ func TestPushResourcesMonitoringWithConfig(t *testing.T) { { name: "SuccessfulMonitoringLongRun", config: &proto.GetResourcesMonitoringConfigurationResponse{ - Enabled: true, Config: &proto.GetResourcesMonitoringConfigurationResponse_Config{ NumDatapoints: 20, CollectionIntervalSeconds: 1, }, - MonitoredVolumes: []string{"/"}, + Volumes: []*proto.GetResourcesMonitoringConfigurationResponse_Volume{ + { + Enabled: true, + Path: "/", + }, + }, }, datapointsPusher: func(_ context.Context, _ *proto.PushResourcesMonitoringUsageRequest) (*proto.PushResourcesMonitoringUsageResponse, error) { return &proto.PushResourcesMonitoringUsageResponse{}, nil diff --git a/coderd/agentapi/resources_monitoring.go b/coderd/agentapi/resources_monitoring.go index c9d390203001e..37cef8eb7d7a8 100644 --- a/coderd/agentapi/resources_monitoring.go +++ b/coderd/agentapi/resources_monitoring.go @@ -21,31 +21,44 @@ type ResourcesMonitoringAPI struct { func (a *ResourcesMonitoringAPI) GetResourcesMonitoringConfiguration(ctx context.Context, _ *proto.GetResourcesMonitoringConfigurationRequest) (*proto.GetResourcesMonitoringConfigurationResponse, error) { agent, err := a.AgentFn(ctx) if err != nil { - return nil, err + return nil, xerrors.Errorf("failed to fetch agent: %w", err) } - _, err = a.Database.FetchMemoryResourceMonitorsByAgentID(ctx, agent.ID) - if err != nil && !errors.Is(err, sql.ErrNoRows) { - return nil, xerrors.New("failed to fetch memory resource monitors") + memoryMonitor, memoryErr := a.Database.FetchMemoryResourceMonitorsByAgentID(ctx, agent.ID) + if memoryErr != nil && !errors.Is(memoryErr, sql.ErrNoRows) { + return nil, xerrors.Errorf("failed to fetch memory resource monitor: %w", memoryErr) } volumeMonitors, err := a.Database.FetchVolumesResourceMonitorsByAgentID(ctx, agent.ID) if err != nil { - return nil, err - } - - volumes := make([]string, 0, len(volumeMonitors)) - for _, monitor := range volumeMonitors { - volumes = append(volumes, monitor.Path) + return nil, xerrors.Errorf("failed to fetch volume resource monitors: %w", err) } return &proto.GetResourcesMonitoringConfigurationResponse{ - Enabled: false, Config: &proto.GetResourcesMonitoringConfigurationResponse_Config{ CollectionIntervalSeconds: 10, NumDatapoints: 20, }, - MonitoredVolumes: volumes, + Memory: func() *proto.GetResourcesMonitoringConfigurationResponse_Memory { + if memoryErr != nil { + return nil + } + + return &proto.GetResourcesMonitoringConfigurationResponse_Memory{ + Enabled: memoryMonitor.Enabled, + } + }(), + Volumes: func() []*proto.GetResourcesMonitoringConfigurationResponse_Volume { + volumes := make([]*proto.GetResourcesMonitoringConfigurationResponse_Volume, 0, len(volumeMonitors)) + for _, monitor := range volumeMonitors { + volumes = append(volumes, &proto.GetResourcesMonitoringConfigurationResponse_Volume{ + Enabled: monitor.Enabled, + Path: monitor.Path, + }) + } + + return volumes + }(), }, nil } From c79b6cb44e8fa8a243e7783bdc4454d336ffddce Mon Sep 17 00:00:00 2001 From: defelmnq Date: Wed, 12 Feb 2025 22:21:41 +0000 Subject: [PATCH 19/32] change proto payload for get resources monitoring config --- agent/proto/resourcesmonitor/resources_monitor.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/agent/proto/resourcesmonitor/resources_monitor.go b/agent/proto/resourcesmonitor/resources_monitor.go index 5c621886c2213..aaec4eab180bf 100644 --- a/agent/proto/resourcesmonitor/resources_monitor.go +++ b/agent/proto/resourcesmonitor/resources_monitor.go @@ -56,6 +56,10 @@ func (m *monitor) Start(ctx context.Context) error { } for _, volume := range m.config.Volumes { + if !volume.Enabled { + continue + } + volTotal, volUsed, err := m.fetchResourceMonitoredVolume(volume.Path) if err != nil { m.logger.Error(ctx, "failed to fetch volume", slog.Error(err)) From b28d4fad9c1424b23965985177a133cffed14dc7 Mon Sep 17 00:00:00 2001 From: defelmnq Date: Thu, 13 Feb 2025 01:12:13 +0000 Subject: [PATCH 20/32] rework fetcher and tests --- agent/agent.go | 3 +- agent/proto/agent.pb.go | 42 ++--- agent/proto/agent.proto | 2 +- agent/proto/resourcesmonitor/fetcher.go | 61 +++++++ agent/proto/resourcesmonitor/fetcher_test.go | 14 ++ agent/proto/resourcesmonitor/queue.go | 7 +- .../resourcesmonitor/resources_monitor.go | 60 ++----- .../resources_monitor_test.go | 152 +++++++++++++++--- 8 files changed, 240 insertions(+), 101 deletions(-) create mode 100644 agent/proto/resourcesmonitor/fetcher.go create mode 100644 agent/proto/resourcesmonitor/fetcher_test.go diff --git a/agent/agent.go b/agent/agent.go index 2c6b973279577..0f43019d96677 100644 --- a/agent/agent.go +++ b/agent/agent.go @@ -798,10 +798,11 @@ func (a *agent) run() (retErr error) { return xerrors.Errorf("failed to get resources monitoring configuration: %w", err) } - resourcesFetcher, err := clistat.New() + fetcher, err := clistat.New() if err != nil { return xerrors.Errorf("failed to create resources fetcher: %w", err) } + resourcesFetcher := resourcesmonitor.NewResourcesFetcher(fetcher) resourcesmonitor := resourcesmonitor.NewResourcesMonitor(logger, clk, config, resourcesFetcher, aAPI) return resourcesmonitor.Start(ctx) diff --git a/agent/proto/agent.pb.go b/agent/proto/agent.pb.go index f60d20765a13c..613ce3d2d6bff 100644 --- a/agent/proto/agent.pb.go +++ b/agent/proto/agent.pb.go @@ -3047,7 +3047,7 @@ type PushResourcesMonitoringUsageRequest_Datapoint struct { unknownFields protoimpl.UnknownFields CollectedAt *timestamppb.Timestamp `protobuf:"bytes,1,opt,name=collected_at,json=collectedAt,proto3" json:"collected_at,omitempty"` - Memory *PushResourcesMonitoringUsageRequest_Datapoint_MemoryUsage `protobuf:"bytes,2,opt,name=memory,proto3" json:"memory,omitempty"` + Memory *PushResourcesMonitoringUsageRequest_Datapoint_MemoryUsage `protobuf:"bytes,2,opt,name=memory,proto3,oneof" json:"memory,omitempty"` Volumes []*PushResourcesMonitoringUsageRequest_Datapoint_VolumeUsage `protobuf:"bytes,3,rep,name=volumes,proto3" json:"volumes,omitempty"` } @@ -3653,7 +3653,7 @@ var file_agent_proto_agent_proto_rawDesc = []byte{ 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x65, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x70, 0x61, 0x74, 0x68, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x70, 0x61, 0x74, 0x68, 0x42, 0x09, 0x0a, 0x07, 0x5f, 0x6d, 0x65, - 0x6d, 0x6f, 0x72, 0x79, 0x22, 0xa3, 0x04, 0x0a, 0x23, 0x50, 0x75, 0x73, 0x68, 0x52, 0x65, 0x73, + 0x6d, 0x6f, 0x72, 0x79, 0x22, 0xb3, 0x04, 0x0a, 0x23, 0x50, 0x75, 0x73, 0x68, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x5d, 0x0a, 0x0a, 0x64, 0x61, 0x74, 0x61, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, @@ -3661,33 +3661,34 @@ var file_agent_proto_agent_proto_rawDesc = []byte{ 0x32, 0x2e, 0x50, 0x75, 0x73, 0x68, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x52, - 0x0a, 0x64, 0x61, 0x74, 0x61, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x1a, 0x9c, 0x03, 0x0a, 0x09, + 0x0a, 0x64, 0x61, 0x74, 0x61, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x73, 0x1a, 0xac, 0x03, 0x0a, 0x09, 0x44, 0x61, 0x74, 0x61, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x12, 0x3d, 0x0a, 0x0c, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0b, 0x63, 0x6f, 0x6c, - 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x61, 0x0a, 0x06, 0x6d, 0x65, 0x6d, 0x6f, + 0x6c, 0x65, 0x63, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x66, 0x0a, 0x06, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x49, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x50, 0x75, 0x73, 0x68, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x2e, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x55, 0x73, - 0x61, 0x67, 0x65, 0x52, 0x06, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x12, 0x63, 0x0a, 0x07, 0x76, - 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x49, 0x2e, 0x63, - 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, 0x76, 0x32, 0x2e, 0x50, 0x75, - 0x73, 0x68, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x4d, 0x6f, 0x6e, 0x69, 0x74, - 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x70, 0x6f, 0x69, 0x6e, 0x74, 0x2e, 0x56, 0x6f, 0x6c, 0x75, - 0x6d, 0x65, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x07, 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x73, - 0x1a, 0x37, 0x0a, 0x0b, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x55, 0x73, 0x61, 0x67, 0x65, 0x12, - 0x12, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x75, - 0x73, 0x65, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x03, 0x52, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x1a, 0x4f, 0x0a, 0x0b, 0x56, 0x6f, 0x6c, - 0x75, 0x6d, 0x65, 0x55, 0x73, 0x61, 0x67, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x76, 0x6f, 0x6c, 0x75, - 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, - 0x12, 0x12, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, - 0x75, 0x73, 0x65, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x22, 0x26, 0x0a, 0x24, 0x50, 0x75, + 0x61, 0x67, 0x65, 0x48, 0x00, 0x52, 0x06, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x88, 0x01, 0x01, + 0x12, 0x63, 0x0a, 0x07, 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x49, 0x2e, 0x63, 0x6f, 0x64, 0x65, 0x72, 0x2e, 0x61, 0x67, 0x65, 0x6e, 0x74, 0x2e, + 0x76, 0x32, 0x2e, 0x50, 0x75, 0x73, 0x68, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, + 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x44, 0x61, 0x74, 0x61, 0x70, 0x6f, 0x69, 0x6e, 0x74, + 0x2e, 0x56, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x07, 0x76, 0x6f, + 0x6c, 0x75, 0x6d, 0x65, 0x73, 0x1a, 0x37, 0x0a, 0x0b, 0x4d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x55, + 0x73, 0x61, 0x67, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x03, 0x52, 0x04, 0x75, 0x73, 0x65, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x74, 0x61, + 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x1a, 0x4f, + 0x0a, 0x0b, 0x56, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x55, 0x73, 0x61, 0x67, 0x65, 0x12, 0x16, 0x0a, + 0x06, 0x76, 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x76, + 0x6f, 0x6c, 0x75, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x75, 0x73, 0x65, 0x64, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x04, 0x75, 0x73, 0x65, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x74, + 0x61, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x42, + 0x09, 0x0a, 0x07, 0x5f, 0x6d, 0x65, 0x6d, 0x6f, 0x72, 0x79, 0x22, 0x26, 0x0a, 0x24, 0x50, 0x75, 0x73, 0x68, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x4d, 0x6f, 0x6e, 0x69, 0x74, 0x6f, 0x72, 0x69, 0x6e, 0x67, 0x55, 0x73, 0x61, 0x67, 0x65, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x2a, 0x63, 0x0a, 0x09, 0x41, 0x70, 0x70, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x12, @@ -4472,6 +4473,7 @@ func file_agent_proto_agent_proto_init() { } } file_agent_proto_agent_proto_msgTypes[29].OneofWrappers = []interface{}{} + file_agent_proto_agent_proto_msgTypes[43].OneofWrappers = []interface{}{} type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ diff --git a/agent/proto/agent.proto b/agent/proto/agent.proto index ce9e676e6f830..6bb802d9664f7 100644 --- a/agent/proto/agent.proto +++ b/agent/proto/agent.proto @@ -330,7 +330,7 @@ message PushResourcesMonitoringUsageRequest { } google.protobuf.Timestamp collected_at = 1; - MemoryUsage memory = 2; + optional MemoryUsage memory = 2; repeated VolumeUsage volumes = 3; } diff --git a/agent/proto/resourcesmonitor/fetcher.go b/agent/proto/resourcesmonitor/fetcher.go new file mode 100644 index 0000000000000..484343f3ff4c5 --- /dev/null +++ b/agent/proto/resourcesmonitor/fetcher.go @@ -0,0 +1,61 @@ +package resourcesmonitor + +import ( + "golang.org/x/xerrors" + + "github.com/coder/coder/v2/cli/clistat" +) + +type ResourcesFetcher interface { + FetchResourceMonitoredMemory() (total int64, used int64, err error) + FetchResourceMonitoredVolume(volume string) (total int64, used int64, err error) +} + +type resourcesFetcher struct { + fetcher *clistat.Statter +} + +//nolint:revive +func NewResourcesFetcher(fetcher *clistat.Statter) *resourcesFetcher { + return &resourcesFetcher{ + fetcher: fetcher, + } +} + +func (f *resourcesFetcher) FetchResourceMonitoredMemory() (total int64, used int64, err error) { + mem, err := f.fetcher.HostMemory(clistat.PrefixMebi) + if err != nil { + return 0, 0, err + } + + var memTotal, memUsed int64 + if mem.Total == nil { + return 0, 0, xerrors.New("memory total is nil - can not fetch memory") + } + + memTotal = f.bytesToMegabytes(int64(*mem.Total)) + memUsed = f.bytesToMegabytes(int64(mem.Used)) + + return memTotal, memUsed, nil +} + +func (f *resourcesFetcher) FetchResourceMonitoredVolume(volume string) (total int64, used int64, err error) { + vol, err := f.fetcher.Disk(clistat.PrefixMebi, volume) + if err != nil { + return 0, 0, err + } + + var volTotal, volUsed int64 + if vol.Total == nil { + return 0, 0, xerrors.New("volume total is nil - can not fetch volume") + } + + volTotal = f.bytesToMegabytes(int64(*vol.Total)) + volUsed = f.bytesToMegabytes(int64(vol.Used)) + + return volTotal, volUsed, nil +} + +func (*resourcesFetcher) bytesToMegabytes(bytes int64) int64 { + return bytes / (1024 * 1024) +} diff --git a/agent/proto/resourcesmonitor/fetcher_test.go b/agent/proto/resourcesmonitor/fetcher_test.go new file mode 100644 index 0000000000000..6e1067b14095d --- /dev/null +++ b/agent/proto/resourcesmonitor/fetcher_test.go @@ -0,0 +1,14 @@ +package resourcesmonitor_test + +type resourcesFetcherMock struct { + fetchResourcesMonitoredMemoryFunc func() (total int64, used int64, err error) + fetchResourcesMonitoredVolumeFunc func(volume string) (total int64, used int64, err error) +} + +func (r *resourcesFetcherMock) FetchResourceMonitoredMemory() (total int64, used int64, err error) { + return r.fetchResourcesMonitoredMemoryFunc() +} + +func (r *resourcesFetcherMock) FetchResourceMonitoredVolume(volume string) (total int64, used int64, err error) { + return r.fetchResourcesMonitoredVolumeFunc(volume) +} diff --git a/agent/proto/resourcesmonitor/queue.go b/agent/proto/resourcesmonitor/queue.go index 65b61ee209f9d..189b1ce8ab8ae 100644 --- a/agent/proto/resourcesmonitor/queue.go +++ b/agent/proto/resourcesmonitor/queue.go @@ -55,11 +55,12 @@ func (q *Queue) ItemsAsProto() []*proto.PushResourcesMonitoringUsageRequest_Data items := make([]*proto.PushResourcesMonitoringUsageRequest_Datapoint, 0, len(q.items)) for _, item := range q.items { - protoItem := &proto.PushResourcesMonitoringUsageRequest_Datapoint{ - Memory: &proto.PushResourcesMonitoringUsageRequest_Datapoint_MemoryUsage{ + protoItem := &proto.PushResourcesMonitoringUsageRequest_Datapoint{} + if item.Memory != nil { + protoItem.Memory = &proto.PushResourcesMonitoringUsageRequest_Datapoint_MemoryUsage{ Total: item.Memory.Total, Used: item.Memory.Used, - }, + } } for _, volume := range item.Volumes { diff --git a/agent/proto/resourcesmonitor/resources_monitor.go b/agent/proto/resourcesmonitor/resources_monitor.go index aaec4eab180bf..fd0550ece3b90 100644 --- a/agent/proto/resourcesmonitor/resources_monitor.go +++ b/agent/proto/resourcesmonitor/resources_monitor.go @@ -4,11 +4,8 @@ import ( "context" "time" - "golang.org/x/xerrors" - "cdr.dev/slog" "github.com/coder/coder/v2/agent/proto" - "github.com/coder/coder/v2/cli/clistat" "github.com/coder/quartz" ) @@ -16,13 +13,13 @@ type monitor struct { logger slog.Logger clock quartz.Clock config *proto.GetResourcesMonitoringConfigurationResponse - resourcesFetcher *clistat.Statter + resourcesFetcher ResourcesFetcher datapointsPusher datapointsPusher queue *Queue } //nolint:revive -func NewResourcesMonitor(logger slog.Logger, clock quartz.Clock, config *proto.GetResourcesMonitoringConfigurationResponse, resourcesFetcher *clistat.Statter, datapointsPusher datapointsPusher) *monitor { +func NewResourcesMonitor(logger slog.Logger, clock quartz.Clock, config *proto.GetResourcesMonitoringConfigurationResponse, resourcesFetcher ResourcesFetcher, datapointsPusher datapointsPusher) *monitor { return &monitor{ logger: logger, clock: clock, @@ -44,14 +41,14 @@ func (m *monitor) Start(ctx context.Context) error { } if m.config.Memory != nil && !m.config.Memory.Enabled { - memTotal, memUsed, err := m.fetchResourceMonitoredMemory() + memTotal, memUsed, err := m.resourcesFetcher.FetchResourceMonitoredMemory() if err != nil { m.logger.Error(ctx, "failed to fetch memory", slog.Error(err)) - return nil - } - datapoint.Memory = &MemoryDatapoint{ - Total: memTotal, - Used: memUsed, + } else { + datapoint.Memory = &MemoryDatapoint{ + Total: memTotal, + Used: memUsed, + } } } @@ -60,7 +57,7 @@ func (m *monitor) Start(ctx context.Context) error { continue } - volTotal, volUsed, err := m.fetchResourceMonitoredVolume(volume.Path) + volTotal, volUsed, err := m.resourcesFetcher.FetchResourceMonitoredVolume(volume.Path) if err != nil { m.logger.Error(ctx, "failed to fetch volume", slog.Error(err)) continue @@ -84,6 +81,7 @@ func (m *monitor) Start(ctx context.Context) error { // to the server. We just log the error and continue. // The queue will anyway remove the oldest datapoint and add the new one. m.logger.Error(ctx, "failed to push resources monitoring usage", slog.Error(err)) + return nil } } @@ -92,41 +90,3 @@ func (m *monitor) Start(ctx context.Context) error { return nil } - -func (m *monitor) fetchResourceMonitoredMemory() (total int64, used int64, err error) { - mem, err := m.resourcesFetcher.HostMemory(clistat.PrefixMebi) - if err != nil { - return 0, 0, err - } - - var memTotal, memUsed int64 - if mem.Total == nil { - return 0, 0, xerrors.New("memory total is nil - can not fetch memory") - } - - memTotal = m.bytesToMegabytes(int64(*mem.Total)) - memUsed = m.bytesToMegabytes(int64(mem.Used)) - - return memTotal, memUsed, nil -} - -func (m *monitor) fetchResourceMonitoredVolume(volume string) (total int64, used int64, err error) { - vol, err := m.resourcesFetcher.Disk(clistat.PrefixMebi, volume) - if err != nil { - return 0, 0, err - } - - var volTotal, volUsed int64 - if vol.Total == nil { - return 0, 0, xerrors.New("volume total is nil - can not fetch volume") - } - - volTotal = m.bytesToMegabytes(int64(*vol.Total)) - volUsed = m.bytesToMegabytes(int64(vol.Used)) - - return volTotal, volUsed, nil -} - -func (*monitor) bytesToMegabytes(bytes int64) int64 { - return bytes / (1024 * 1024) -} diff --git a/agent/proto/resourcesmonitor/resources_monitor_test.go b/agent/proto/resourcesmonitor/resources_monitor_test.go index c3786cf10879a..245951ad6e59a 100644 --- a/agent/proto/resourcesmonitor/resources_monitor_test.go +++ b/agent/proto/resourcesmonitor/resources_monitor_test.go @@ -5,13 +5,13 @@ import ( "os" "testing" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "cdr.dev/slog" "cdr.dev/slog/sloggers/sloghuman" "github.com/coder/coder/v2/agent/proto" "github.com/coder/coder/v2/agent/proto/resourcesmonitor" - "github.com/coder/coder/v2/cli/clistat" "github.com/coder/quartz" ) @@ -25,14 +25,13 @@ func (d *datapointsPusherMock) PushResourcesMonitoringUsage(ctx context.Context, func TestPushResourcesMonitoringWithConfig(t *testing.T) { t.Parallel() - tests := []struct { - name string - config *proto.GetResourcesMonitoringConfigurationResponse - datapointsPusher func(ctx context.Context, req *proto.PushResourcesMonitoringUsageRequest) (*proto.PushResourcesMonitoringUsageResponse, error) - expectedError bool - numTicks int - expectedCalls int + name string + config *proto.GetResourcesMonitoringConfigurationResponse + datapointsPusher func(ctx context.Context, req *proto.PushResourcesMonitoringUsageRequest) (*proto.PushResourcesMonitoringUsageResponse, error) + fetchResourcesMonitoredMemoryFunc func() (int64, int64, error) + fetchResourcesMonitoredVolumeFunc func(volume string) (int64, int64, error) + numTicks int }{ { name: "SuccessfulMonitoring", @@ -51,9 +50,13 @@ func TestPushResourcesMonitoringWithConfig(t *testing.T) { datapointsPusher: func(_ context.Context, _ *proto.PushResourcesMonitoringUsageRequest) (*proto.PushResourcesMonitoringUsageResponse, error) { return &proto.PushResourcesMonitoringUsageResponse{}, nil }, - expectedError: false, - numTicks: 20, - expectedCalls: 1, + fetchResourcesMonitoredMemoryFunc: func() (int64, int64, error) { + return 1000, 8000, nil + }, + fetchResourcesMonitoredVolumeFunc: func(_ string) (int64, int64, error) { + return 50000, 100000, nil + }, + numTicks: 20, }, { name: "SuccessfulMonitoringLongRun", @@ -72,9 +75,107 @@ func TestPushResourcesMonitoringWithConfig(t *testing.T) { datapointsPusher: func(_ context.Context, _ *proto.PushResourcesMonitoringUsageRequest) (*proto.PushResourcesMonitoringUsageResponse, error) { return &proto.PushResourcesMonitoringUsageResponse{}, nil }, - expectedError: false, - numTicks: 60, - expectedCalls: 41, + fetchResourcesMonitoredMemoryFunc: func() (int64, int64, error) { + return 1000, 8000, nil + }, + fetchResourcesMonitoredVolumeFunc: func(_ string) (int64, int64, error) { + return 50000, 100000, nil + }, + numTicks: 60, + }, + { + // We want to make sure that even if the datapointsPusher fails, the monitoring continues. + name: "ErrorPushingDatapoints", + config: &proto.GetResourcesMonitoringConfigurationResponse{ + Config: &proto.GetResourcesMonitoringConfigurationResponse_Config{ + NumDatapoints: 20, + CollectionIntervalSeconds: 1, + }, + Volumes: []*proto.GetResourcesMonitoringConfigurationResponse_Volume{ + { + Enabled: true, + Path: "/", + }, + }, + }, + datapointsPusher: func(_ context.Context, _ *proto.PushResourcesMonitoringUsageRequest) (*proto.PushResourcesMonitoringUsageResponse, error) { + return nil, assert.AnError + }, + fetchResourcesMonitoredMemoryFunc: func() (int64, int64, error) { + return 1000, 8000, nil + }, + fetchResourcesMonitoredVolumeFunc: func(_ string) (int64, int64, error) { + return 50000, 100000, nil + }, + numTicks: 60, + }, + { + // If one of the resources fails to be fetched, the datapoints still should be pushed with the other resources. + name: "ErrorFetchingMemory", + config: &proto.GetResourcesMonitoringConfigurationResponse{ + Config: &proto.GetResourcesMonitoringConfigurationResponse_Config{ + NumDatapoints: 20, + CollectionIntervalSeconds: 1, + }, + Volumes: []*proto.GetResourcesMonitoringConfigurationResponse_Volume{ + { + Enabled: true, + Path: "/", + }, + }, + }, + datapointsPusher: func(_ context.Context, req *proto.PushResourcesMonitoringUsageRequest) (*proto.PushResourcesMonitoringUsageResponse, error) { + require.Len(t, req.Datapoints, 20) + require.Nil(t, req.Datapoints[0].Memory) + require.NotNil(t, req.Datapoints[0].Volumes) + require.Equal(t, &proto.PushResourcesMonitoringUsageRequest_Datapoint_VolumeUsage{ + Volume: "/", + Total: 100000, + Used: 50000, + }, req.Datapoints[0].Volumes[0]) + + return &proto.PushResourcesMonitoringUsageResponse{}, nil + }, + fetchResourcesMonitoredMemoryFunc: func() (int64, int64, error) { + return 0, 0, assert.AnError + }, + fetchResourcesMonitoredVolumeFunc: func(_ string) (int64, int64, error) { + return 100000, 50000, nil + }, + numTicks: 20, + }, + { + // If one of the resources fails to be fetched, the datapoints still should be pushed with the other resources. + name: "ErrorFetchingVolume", + config: &proto.GetResourcesMonitoringConfigurationResponse{ + Config: &proto.GetResourcesMonitoringConfigurationResponse_Config{ + NumDatapoints: 20, + CollectionIntervalSeconds: 1, + }, + Volumes: []*proto.GetResourcesMonitoringConfigurationResponse_Volume{ + { + Enabled: true, + Path: "/", + }, + }, + }, + datapointsPusher: func(_ context.Context, req *proto.PushResourcesMonitoringUsageRequest) (*proto.PushResourcesMonitoringUsageResponse, error) { + require.Len(t, req.Datapoints, 20) + require.Len(t, req.Datapoints[0].Volumes, 0) + require.Equal(t, &proto.PushResourcesMonitoringUsageRequest_Datapoint_MemoryUsage{ + Total: 1000, + Used: 8000, + }, req.Datapoints[0].Memory) + + return &proto.PushResourcesMonitoringUsageResponse{}, nil + }, + fetchResourcesMonitoredMemoryFunc: func() (int64, int64, error) { + return 1000, 8000, nil + }, + fetchResourcesMonitoredVolumeFunc: func(_ string) (int64, int64, error) { + return 0, 0, assert.AnError + }, + numTicks: 20, }, } @@ -92,33 +193,32 @@ func TestPushResourcesMonitoringWithConfig(t *testing.T) { counterCalls = 0 ) - datapointsPusher := func(ctx context.Context, params *proto.PushResourcesMonitoringUsageRequest) (*proto.PushResourcesMonitoringUsageResponse, error) { + datapointsPusher := func(ctx context.Context, req *proto.PushResourcesMonitoringUsageRequest) (*proto.PushResourcesMonitoringUsageResponse, error) { counterCalls++ - return tt.datapointsPusher(ctx, params) + return tt.datapointsPusher(ctx, req) } pusher := &datapointsPusherMock{ PushResourcesMonitoringUsageFunc: datapointsPusher, } - resourcesFetcher, err := clistat.New() - require.NoError(t, err) - - monitor := resourcesmonitor.NewResourcesMonitor(logger, clk, tt.config, resourcesFetcher, pusher) - err = monitor.Start(ctx) - if tt.expectedError { - require.Error(t, err) - return + resourcesFetcher := &resourcesFetcherMock{ + fetchResourcesMonitoredMemoryFunc: tt.fetchResourcesMonitoredMemoryFunc, + fetchResourcesMonitoredVolumeFunc: tt.fetchResourcesMonitoredVolumeFunc, } - require.NoError(t, err) + monitor := resourcesmonitor.NewResourcesMonitor(logger, clk, tt.config, resourcesFetcher, pusher) + require.NoError(t, monitor.Start(ctx)) for i := 0; i < tt.numTicks; i++ { _, waiter := clk.AdvanceNext() require.NoError(t, waiter.Wait(ctx)) } - require.Equal(t, tt.expectedCalls, counterCalls) + // expectedCalls is computed with the following logic : + // We have one call per tick, once reached the ${config.NumDatapoints}. + expectedCalls := tt.numTicks - int(tt.config.Config.NumDatapoints) + 1 + require.Equal(t, expectedCalls, counterCalls) cancel() }) } From 770162420d08ee6019a2bd715b1450c9c727defd Mon Sep 17 00:00:00 2001 From: defelmnq Date: Thu, 13 Feb 2025 01:41:44 +0000 Subject: [PATCH 21/32] fix tests --- agent/agenttest/client.go | 4 +++- agent/proto/resourcesmonitor/resources_monitor_test.go | 4 ---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/agent/agenttest/client.go b/agent/agenttest/client.go index 4edbc23c571e0..19d39c39dc72b 100644 --- a/agent/agenttest/client.go +++ b/agent/agenttest/client.go @@ -219,7 +219,9 @@ func (f *FakeAgentAPI) GetResourcesMonitoringConfiguration(_ context.Context, _ defer f.Unlock() if f.getResourcesMonitoringConfigurationFunc == nil { - return &agentproto.GetResourcesMonitoringConfigurationResponse{}, nil + return &agentproto.GetResourcesMonitoringConfigurationResponse{ + Config: &agentproto.GetResourcesMonitoringConfigurationResponse_Config{}, + }, nil } return f.getResourcesMonitoringConfigurationFunc() diff --git a/agent/proto/resourcesmonitor/resources_monitor_test.go b/agent/proto/resourcesmonitor/resources_monitor_test.go index 245951ad6e59a..c54b298211d92 100644 --- a/agent/proto/resourcesmonitor/resources_monitor_test.go +++ b/agent/proto/resourcesmonitor/resources_monitor_test.go @@ -162,10 +162,6 @@ func TestPushResourcesMonitoringWithConfig(t *testing.T) { datapointsPusher: func(_ context.Context, req *proto.PushResourcesMonitoringUsageRequest) (*proto.PushResourcesMonitoringUsageResponse, error) { require.Len(t, req.Datapoints, 20) require.Len(t, req.Datapoints[0].Volumes, 0) - require.Equal(t, &proto.PushResourcesMonitoringUsageRequest_Datapoint_MemoryUsage{ - Total: 1000, - Used: 8000, - }, req.Datapoints[0].Memory) return &proto.PushResourcesMonitoringUsageResponse{}, nil }, From 5fad903a0459d95e6326acb5918551c41ee21f43 Mon Sep 17 00:00:00 2001 From: defelmnq Date: Thu, 13 Feb 2025 01:49:32 +0000 Subject: [PATCH 22/32] fix tests --- agent/agenttest/client.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/agent/agenttest/client.go b/agent/agenttest/client.go index 19d39c39dc72b..dc28934162f7f 100644 --- a/agent/agenttest/client.go +++ b/agent/agenttest/client.go @@ -220,7 +220,9 @@ func (f *FakeAgentAPI) GetResourcesMonitoringConfiguration(_ context.Context, _ if f.getResourcesMonitoringConfigurationFunc == nil { return &agentproto.GetResourcesMonitoringConfigurationResponse{ - Config: &agentproto.GetResourcesMonitoringConfigurationResponse_Config{}, + Config: &agentproto.GetResourcesMonitoringConfigurationResponse_Config{ + CollectionIntervalSeconds: 1, + }, }, nil } From b611ae5a25cc28f041569f3be0c58eb93b3949bf Mon Sep 17 00:00:00 2001 From: defelmnq Date: Thu, 13 Feb 2025 01:57:32 +0000 Subject: [PATCH 23/32] fix tests --- agent/agenttest/client.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/agent/agenttest/client.go b/agent/agenttest/client.go index dc28934162f7f..3287274756cad 100644 --- a/agent/agenttest/client.go +++ b/agent/agenttest/client.go @@ -221,7 +221,8 @@ func (f *FakeAgentAPI) GetResourcesMonitoringConfiguration(_ context.Context, _ if f.getResourcesMonitoringConfigurationFunc == nil { return &agentproto.GetResourcesMonitoringConfigurationResponse{ Config: &agentproto.GetResourcesMonitoringConfigurationResponse_Config{ - CollectionIntervalSeconds: 1, + CollectionIntervalSeconds: 10, + NumDatapoints: 20, }, }, nil } From 3c65b8aea189cd802f89b7b86f9fed9a568e886b Mon Sep 17 00:00:00 2001 From: defelmnq Date: Thu, 13 Feb 2025 02:07:24 +0000 Subject: [PATCH 24/32] fix logic --- agent/proto/resourcesmonitor/resources_monitor.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/agent/proto/resourcesmonitor/resources_monitor.go b/agent/proto/resourcesmonitor/resources_monitor.go index fd0550ece3b90..2c3d5ac8c7176 100644 --- a/agent/proto/resourcesmonitor/resources_monitor.go +++ b/agent/proto/resourcesmonitor/resources_monitor.go @@ -40,7 +40,7 @@ func (m *monitor) Start(ctx context.Context) error { Volumes: make([]*VolumeDatapoint, 0, len(m.config.Volumes)), } - if m.config.Memory != nil && !m.config.Memory.Enabled { + if m.config.Memory != nil && m.config.Memory.Enabled { memTotal, memUsed, err := m.resourcesFetcher.FetchResourceMonitoredMemory() if err != nil { m.logger.Error(ctx, "failed to fetch memory", slog.Error(err)) From 63c5869cf05f5250a44371f3939734a8c92a93ff Mon Sep 17 00:00:00 2001 From: defelmnq Date: Thu, 13 Feb 2025 07:54:38 +0000 Subject: [PATCH 25/32] improve testing fetcher and rename struct --- agent/agent.go | 4 +- agent/proto/resourcesmonitor/fetcher.go | 40 +++------ agent/proto/resourcesmonitor/fetcher_test.go | 14 --- .../resourcesmonitor/resources_monitor.go | 8 +- .../resources_monitor_test.go | 88 +++++++++++-------- 5 files changed, 71 insertions(+), 83 deletions(-) delete mode 100644 agent/proto/resourcesmonitor/fetcher_test.go diff --git a/agent/agent.go b/agent/agent.go index 0f43019d96677..6a26a7a3d8b87 100644 --- a/agent/agent.go +++ b/agent/agent.go @@ -798,11 +798,11 @@ func (a *agent) run() (retErr error) { return xerrors.Errorf("failed to get resources monitoring configuration: %w", err) } - fetcher, err := clistat.New() + statfetcher, err := clistat.New() if err != nil { return xerrors.Errorf("failed to create resources fetcher: %w", err) } - resourcesFetcher := resourcesmonitor.NewResourcesFetcher(fetcher) + resourcesFetcher := resourcesmonitor.NewFetcher(statfetcher) resourcesmonitor := resourcesmonitor.NewResourcesMonitor(logger, clk, config, resourcesFetcher, aAPI) return resourcesmonitor.Start(ctx) diff --git a/agent/proto/resourcesmonitor/fetcher.go b/agent/proto/resourcesmonitor/fetcher.go index 484343f3ff4c5..b8485ed13dcb7 100644 --- a/agent/proto/resourcesmonitor/fetcher.go +++ b/agent/proto/resourcesmonitor/fetcher.go @@ -6,56 +6,44 @@ import ( "github.com/coder/coder/v2/cli/clistat" ) -type ResourcesFetcher interface { - FetchResourceMonitoredMemory() (total int64, used int64, err error) - FetchResourceMonitoredVolume(volume string) (total int64, used int64, err error) +type Fetcher interface { + FetchMemory() (total int64, used int64, err error) + FetchVolume(volume string) (total int64, used int64, err error) } -type resourcesFetcher struct { - fetcher *clistat.Statter +type fetcher struct { + *clistat.Statter } //nolint:revive -func NewResourcesFetcher(fetcher *clistat.Statter) *resourcesFetcher { - return &resourcesFetcher{ - fetcher: fetcher, +func NewFetcher(f *clistat.Statter) *fetcher { + return &fetcher{ + f, } } -func (f *resourcesFetcher) FetchResourceMonitoredMemory() (total int64, used int64, err error) { - mem, err := f.fetcher.HostMemory(clistat.PrefixMebi) +func (f *fetcher) FetchMemory() (total int64, used int64, err error) { + mem, err := f.HostMemory(clistat.PrefixDefault) if err != nil { return 0, 0, err } - var memTotal, memUsed int64 if mem.Total == nil { return 0, 0, xerrors.New("memory total is nil - can not fetch memory") } - memTotal = f.bytesToMegabytes(int64(*mem.Total)) - memUsed = f.bytesToMegabytes(int64(mem.Used)) - - return memTotal, memUsed, nil + return int64(*mem.Total), int64(mem.Used), nil } -func (f *resourcesFetcher) FetchResourceMonitoredVolume(volume string) (total int64, used int64, err error) { - vol, err := f.fetcher.Disk(clistat.PrefixMebi, volume) +func (f *fetcher) FetchVolume(volume string) (total int64, used int64, err error) { + vol, err := f.Disk(clistat.PrefixDefault, volume) if err != nil { return 0, 0, err } - var volTotal, volUsed int64 if vol.Total == nil { return 0, 0, xerrors.New("volume total is nil - can not fetch volume") } - volTotal = f.bytesToMegabytes(int64(*vol.Total)) - volUsed = f.bytesToMegabytes(int64(vol.Used)) - - return volTotal, volUsed, nil -} - -func (*resourcesFetcher) bytesToMegabytes(bytes int64) int64 { - return bytes / (1024 * 1024) + return int64(*vol.Total), int64(vol.Used), nil } diff --git a/agent/proto/resourcesmonitor/fetcher_test.go b/agent/proto/resourcesmonitor/fetcher_test.go deleted file mode 100644 index 6e1067b14095d..0000000000000 --- a/agent/proto/resourcesmonitor/fetcher_test.go +++ /dev/null @@ -1,14 +0,0 @@ -package resourcesmonitor_test - -type resourcesFetcherMock struct { - fetchResourcesMonitoredMemoryFunc func() (total int64, used int64, err error) - fetchResourcesMonitoredVolumeFunc func(volume string) (total int64, used int64, err error) -} - -func (r *resourcesFetcherMock) FetchResourceMonitoredMemory() (total int64, used int64, err error) { - return r.fetchResourcesMonitoredMemoryFunc() -} - -func (r *resourcesFetcherMock) FetchResourceMonitoredVolume(volume string) (total int64, used int64, err error) { - return r.fetchResourcesMonitoredVolumeFunc(volume) -} diff --git a/agent/proto/resourcesmonitor/resources_monitor.go b/agent/proto/resourcesmonitor/resources_monitor.go index 2c3d5ac8c7176..d17d851fbd97f 100644 --- a/agent/proto/resourcesmonitor/resources_monitor.go +++ b/agent/proto/resourcesmonitor/resources_monitor.go @@ -13,13 +13,13 @@ type monitor struct { logger slog.Logger clock quartz.Clock config *proto.GetResourcesMonitoringConfigurationResponse - resourcesFetcher ResourcesFetcher + resourcesFetcher Fetcher datapointsPusher datapointsPusher queue *Queue } //nolint:revive -func NewResourcesMonitor(logger slog.Logger, clock quartz.Clock, config *proto.GetResourcesMonitoringConfigurationResponse, resourcesFetcher ResourcesFetcher, datapointsPusher datapointsPusher) *monitor { +func NewResourcesMonitor(logger slog.Logger, clock quartz.Clock, config *proto.GetResourcesMonitoringConfigurationResponse, resourcesFetcher Fetcher, datapointsPusher datapointsPusher) *monitor { return &monitor{ logger: logger, clock: clock, @@ -41,7 +41,7 @@ func (m *monitor) Start(ctx context.Context) error { } if m.config.Memory != nil && m.config.Memory.Enabled { - memTotal, memUsed, err := m.resourcesFetcher.FetchResourceMonitoredMemory() + memTotal, memUsed, err := m.resourcesFetcher.FetchMemory() if err != nil { m.logger.Error(ctx, "failed to fetch memory", slog.Error(err)) } else { @@ -57,7 +57,7 @@ func (m *monitor) Start(ctx context.Context) error { continue } - volTotal, volUsed, err := m.resourcesFetcher.FetchResourceMonitoredVolume(volume.Path) + volTotal, volUsed, err := m.resourcesFetcher.FetchVolume(volume.Path) if err != nil { m.logger.Error(ctx, "failed to fetch volume", slog.Error(err)) continue diff --git a/agent/proto/resourcesmonitor/resources_monitor_test.go b/agent/proto/resourcesmonitor/resources_monitor_test.go index c54b298211d92..08a342befb3a6 100644 --- a/agent/proto/resourcesmonitor/resources_monitor_test.go +++ b/agent/proto/resourcesmonitor/resources_monitor_test.go @@ -23,15 +23,32 @@ func (d *datapointsPusherMock) PushResourcesMonitoringUsage(ctx context.Context, return d.PushResourcesMonitoringUsageFunc(ctx, req) } +type fetcher struct { + totalMemory int64 + usedMemory int64 + totalVolume int64 + usedVolume int64 + + errMemory error + errVolume error +} + +func (r *fetcher) FetchMemory() (total int64, used int64, err error) { + return r.totalMemory, r.usedMemory, r.errMemory +} + +func (r *fetcher) FetchVolume(volume string) (total int64, used int64, err error) { + return r.totalVolume, r.usedVolume, r.errVolume +} + func TestPushResourcesMonitoringWithConfig(t *testing.T) { t.Parallel() tests := []struct { - name string - config *proto.GetResourcesMonitoringConfigurationResponse - datapointsPusher func(ctx context.Context, req *proto.PushResourcesMonitoringUsageRequest) (*proto.PushResourcesMonitoringUsageResponse, error) - fetchResourcesMonitoredMemoryFunc func() (int64, int64, error) - fetchResourcesMonitoredVolumeFunc func(volume string) (int64, int64, error) - numTicks int + name string + config *proto.GetResourcesMonitoringConfigurationResponse + datapointsPusher func(ctx context.Context, req *proto.PushResourcesMonitoringUsageRequest) (*proto.PushResourcesMonitoringUsageResponse, error) + fetcher resourcesmonitor.Fetcher + numTicks int }{ { name: "SuccessfulMonitoring", @@ -50,11 +67,11 @@ func TestPushResourcesMonitoringWithConfig(t *testing.T) { datapointsPusher: func(_ context.Context, _ *proto.PushResourcesMonitoringUsageRequest) (*proto.PushResourcesMonitoringUsageResponse, error) { return &proto.PushResourcesMonitoringUsageResponse{}, nil }, - fetchResourcesMonitoredMemoryFunc: func() (int64, int64, error) { - return 1000, 8000, nil - }, - fetchResourcesMonitoredVolumeFunc: func(_ string) (int64, int64, error) { - return 50000, 100000, nil + fetcher: &fetcher{ + totalMemory: 16000, + usedMemory: 8000, + totalVolume: 100000, + usedVolume: 50000, }, numTicks: 20, }, @@ -75,11 +92,11 @@ func TestPushResourcesMonitoringWithConfig(t *testing.T) { datapointsPusher: func(_ context.Context, _ *proto.PushResourcesMonitoringUsageRequest) (*proto.PushResourcesMonitoringUsageResponse, error) { return &proto.PushResourcesMonitoringUsageResponse{}, nil }, - fetchResourcesMonitoredMemoryFunc: func() (int64, int64, error) { - return 1000, 8000, nil - }, - fetchResourcesMonitoredVolumeFunc: func(_ string) (int64, int64, error) { - return 50000, 100000, nil + fetcher: &fetcher{ + totalMemory: 16000, + usedMemory: 8000, + totalVolume: 100000, + usedVolume: 50000, }, numTicks: 60, }, @@ -101,11 +118,11 @@ func TestPushResourcesMonitoringWithConfig(t *testing.T) { datapointsPusher: func(_ context.Context, _ *proto.PushResourcesMonitoringUsageRequest) (*proto.PushResourcesMonitoringUsageResponse, error) { return nil, assert.AnError }, - fetchResourcesMonitoredMemoryFunc: func() (int64, int64, error) { - return 1000, 8000, nil - }, - fetchResourcesMonitoredVolumeFunc: func(_ string) (int64, int64, error) { - return 50000, 100000, nil + fetcher: &fetcher{ + totalMemory: 16000, + usedMemory: 8000, + totalVolume: 100000, + usedVolume: 50000, }, numTicks: 60, }, @@ -136,11 +153,12 @@ func TestPushResourcesMonitoringWithConfig(t *testing.T) { return &proto.PushResourcesMonitoringUsageResponse{}, nil }, - fetchResourcesMonitoredMemoryFunc: func() (int64, int64, error) { - return 0, 0, assert.AnError - }, - fetchResourcesMonitoredVolumeFunc: func(_ string) (int64, int64, error) { - return 100000, 50000, nil + fetcher: &fetcher{ + totalMemory: 0, + usedMemory: 0, + errMemory: assert.AnError, + totalVolume: 100000, + usedVolume: 50000, }, numTicks: 20, }, @@ -165,11 +183,12 @@ func TestPushResourcesMonitoringWithConfig(t *testing.T) { return &proto.PushResourcesMonitoringUsageResponse{}, nil }, - fetchResourcesMonitoredMemoryFunc: func() (int64, int64, error) { - return 1000, 8000, nil - }, - fetchResourcesMonitoredVolumeFunc: func(_ string) (int64, int64, error) { - return 0, 0, assert.AnError + fetcher: &fetcher{ + totalMemory: 16000, + usedMemory: 8000, + totalVolume: 0, + usedVolume: 0, + errVolume: assert.AnError, }, numTicks: 20, }, @@ -198,12 +217,7 @@ func TestPushResourcesMonitoringWithConfig(t *testing.T) { PushResourcesMonitoringUsageFunc: datapointsPusher, } - resourcesFetcher := &resourcesFetcherMock{ - fetchResourcesMonitoredMemoryFunc: tt.fetchResourcesMonitoredMemoryFunc, - fetchResourcesMonitoredVolumeFunc: tt.fetchResourcesMonitoredVolumeFunc, - } - - monitor := resourcesmonitor.NewResourcesMonitor(logger, clk, tt.config, resourcesFetcher, pusher) + monitor := resourcesmonitor.NewResourcesMonitor(logger, clk, tt.config, tt.fetcher, pusher) require.NoError(t, monitor.Start(ctx)) for i := 0; i < tt.numTicks; i++ { From 2d3eeb5189dfdadad6a0fdd8f49ab50474393f2d Mon Sep 17 00:00:00 2001 From: defelmnq Date: Thu, 13 Feb 2025 08:09:05 +0000 Subject: [PATCH 26/32] lint --- agent/proto/resourcesmonitor/resources_monitor_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/agent/proto/resourcesmonitor/resources_monitor_test.go b/agent/proto/resourcesmonitor/resources_monitor_test.go index 08a342befb3a6..ddf3522ecea30 100644 --- a/agent/proto/resourcesmonitor/resources_monitor_test.go +++ b/agent/proto/resourcesmonitor/resources_monitor_test.go @@ -37,7 +37,7 @@ func (r *fetcher) FetchMemory() (total int64, used int64, err error) { return r.totalMemory, r.usedMemory, r.errMemory } -func (r *fetcher) FetchVolume(volume string) (total int64, used int64, err error) { +func (r *fetcher) FetchVolume(_ string) (total int64, used int64, err error) { return r.totalVolume, r.usedVolume, r.errVolume } From e17aafce05ab768146cbe8842d015ef2f5ce1bac Mon Sep 17 00:00:00 2001 From: defelmnq Date: Thu, 13 Feb 2025 17:06:18 +0000 Subject: [PATCH 27/32] work on dbauthz --- coderd/apidoc/docs.go | 2 + coderd/apidoc/swagger.json | 2 + coderd/database/dbauthz/dbauthz.go | 6 +- coderd/database/dbauthz/dbauthz_test.go | 4 +- coderd/rbac/object_gen.go | 9 + coderd/rbac/policy/policy.go | 6 + codersdk/rbacresources_gen.go | 134 +++---- docs/reference/api/members.md | 485 ++++++++++++------------ docs/reference/api/schemas.md | 71 ++-- site/src/api/rbacresourcesGenerated.ts | 4 + site/src/api/typesGenerated.ts | 2 + 11 files changed, 380 insertions(+), 345 deletions(-) diff --git a/coderd/apidoc/docs.go b/coderd/apidoc/docs.go index 329951003007b..3d4ae52e993db 100644 --- a/coderd/apidoc/docs.go +++ b/coderd/apidoc/docs.go @@ -13475,6 +13475,7 @@ const docTemplate = `{ "template", "user", "workspace", + "workspace_agent_resource_monitor", "workspace_dormant", "workspace_proxy" ], @@ -13510,6 +13511,7 @@ const docTemplate = `{ "ResourceTemplate", "ResourceUser", "ResourceWorkspace", + "ResourceWorkspaceAgentResourceMonitor", "ResourceWorkspaceDormant", "ResourceWorkspaceProxy" ] diff --git a/coderd/apidoc/swagger.json b/coderd/apidoc/swagger.json index 63b7146365d9f..c431f8eca5a50 100644 --- a/coderd/apidoc/swagger.json +++ b/coderd/apidoc/swagger.json @@ -12178,6 +12178,7 @@ "template", "user", "workspace", + "workspace_agent_resource_monitor", "workspace_dormant", "workspace_proxy" ], @@ -12213,6 +12214,7 @@ "ResourceTemplate", "ResourceUser", "ResourceWorkspace", + "ResourceWorkspaceAgentResourceMonitor", "ResourceWorkspaceDormant", "ResourceWorkspaceProxy" ] diff --git a/coderd/database/dbauthz/dbauthz.go b/coderd/database/dbauthz/dbauthz.go index 3f40224875af7..297ce340b1190 100644 --- a/coderd/database/dbauthz/dbauthz.go +++ b/coderd/database/dbauthz/dbauthz.go @@ -184,6 +184,8 @@ var ( rbac.ResourceGroup.Type: {policy.ActionRead}, // Provisionerd creates notification messages rbac.ResourceNotificationMessage.Type: {policy.ActionCreate, policy.ActionRead}, + // Provisionerd creates workspaces resources monitor + rbac.ResourceWorkspaceAgentResourceMonitor.Type: {policy.ActionCreate}, }), Org: map[string][]rbac.Permission{}, User: []rbac.Permission{}, @@ -3012,7 +3014,7 @@ func (q *querier) InsertLicense(ctx context.Context, arg database.InsertLicenseP } func (q *querier) InsertMemoryResourceMonitor(ctx context.Context, arg database.InsertMemoryResourceMonitorParams) (database.WorkspaceAgentMemoryResourceMonitor, error) { - if err := q.authorizeContext(ctx, policy.ActionCreate, rbac.ResourceSystem); err != nil { + if err := q.authorizeContext(ctx, policy.ActionCreate, rbac.ResourceWorkspaceAgentResourceMonitor); err != nil { return database.WorkspaceAgentMemoryResourceMonitor{}, err } @@ -3212,7 +3214,7 @@ func (q *querier) InsertUserLink(ctx context.Context, arg database.InsertUserLin } func (q *querier) InsertVolumeResourceMonitor(ctx context.Context, arg database.InsertVolumeResourceMonitorParams) (database.WorkspaceAgentVolumeResourceMonitor, error) { - if err := q.authorizeContext(ctx, policy.ActionCreate, rbac.ResourceSystem); err != nil { + if err := q.authorizeContext(ctx, policy.ActionCreate, rbac.ResourceWorkspaceAgentResourceMonitor); err != nil { return database.WorkspaceAgentVolumeResourceMonitor{}, err } diff --git a/coderd/database/dbauthz/dbauthz_test.go b/coderd/database/dbauthz/dbauthz_test.go index 1506fdb5b6526..abfb9abfadac4 100644 --- a/coderd/database/dbauthz/dbauthz_test.go +++ b/coderd/database/dbauthz/dbauthz_test.go @@ -4566,12 +4566,12 @@ func (s *MethodTestSuite) TestOAuth2ProviderAppTokens() { func (s *MethodTestSuite) TestResourcesMonitor() { s.Run("InsertMemoryResourceMonitor", s.Subtest(func(db database.Store, check *expects) { dbtestutil.DisableForeignKeysAndTriggers(s.T(), db) - check.Args(database.InsertMemoryResourceMonitorParams{}).Asserts(rbac.ResourceSystem, policy.ActionCreate) + check.Args(database.InsertMemoryResourceMonitorParams{}).Asserts(rbac.ResourceWorkspaceAgentResourceMonitor, policy.ActionCreate) })) s.Run("InsertVolumeResourceMonitor", s.Subtest(func(db database.Store, check *expects) { dbtestutil.DisableForeignKeysAndTriggers(s.T(), db) - check.Args(database.InsertVolumeResourceMonitorParams{}).Asserts(rbac.ResourceSystem, policy.ActionCreate) + check.Args(database.InsertVolumeResourceMonitorParams{}).Asserts(rbac.ResourceWorkspaceAgentResourceMonitor, policy.ActionCreate) })) s.Run("FetchMemoryResourceMonitorsByAgentID", s.Subtest(func(db database.Store, check *expects) { diff --git a/coderd/rbac/object_gen.go b/coderd/rbac/object_gen.go index 42e9e16c50279..547e10859b5b7 100644 --- a/coderd/rbac/object_gen.go +++ b/coderd/rbac/object_gen.go @@ -295,6 +295,14 @@ var ( Type: "workspace", } + // ResourceWorkspaceAgentResourceMonitor + // Valid Actions + // - "ActionCreate" :: create workspace agent resource monitor + // - "ActionRead" :: read workspace agent resource monitor + ResourceWorkspaceAgentResourceMonitor = Object{ + Type: "workspace_agent_resource_monitor", + } + // ResourceWorkspaceDormant // Valid Actions // - "ActionApplicationConnect" :: connect to workspace apps via browser @@ -353,6 +361,7 @@ func AllResources() []Objecter { ResourceTemplate, ResourceUser, ResourceWorkspace, + ResourceWorkspaceAgentResourceMonitor, ResourceWorkspaceDormant, ResourceWorkspaceProxy, } diff --git a/coderd/rbac/policy/policy.go b/coderd/rbac/policy/policy.go index e57c2eaa234f7..6dc64f6660248 100644 --- a/coderd/rbac/policy/policy.go +++ b/coderd/rbac/policy/policy.go @@ -302,4 +302,10 @@ var RBACPermissions = map[string]PermissionDefinition{ ActionUpdate: actDef("update IdP sync settings"), }, }, + "workspace_agent_resource_monitor": { + Actions: map[Action]ActionDefinition{ + ActionRead: actDef("read workspace agent resource monitor"), + ActionCreate: actDef("create workspace agent resource monitor"), + }, + }, } diff --git a/codersdk/rbacresources_gen.go b/codersdk/rbacresources_gen.go index 8de32c107aae4..8afb1858ca15c 100644 --- a/codersdk/rbacresources_gen.go +++ b/codersdk/rbacresources_gen.go @@ -4,39 +4,40 @@ package codersdk type RBACResource string const ( - ResourceWildcard RBACResource = "*" - ResourceApiKey RBACResource = "api_key" - ResourceAssignOrgRole RBACResource = "assign_org_role" - ResourceAssignRole RBACResource = "assign_role" - ResourceAuditLog RBACResource = "audit_log" - ResourceCryptoKey RBACResource = "crypto_key" - ResourceDebugInfo RBACResource = "debug_info" - ResourceDeploymentConfig RBACResource = "deployment_config" - ResourceDeploymentStats RBACResource = "deployment_stats" - ResourceFile RBACResource = "file" - ResourceGroup RBACResource = "group" - ResourceGroupMember RBACResource = "group_member" - ResourceIdpsyncSettings RBACResource = "idpsync_settings" - ResourceLicense RBACResource = "license" - ResourceNotificationMessage RBACResource = "notification_message" - ResourceNotificationPreference RBACResource = "notification_preference" - ResourceNotificationTemplate RBACResource = "notification_template" - ResourceOauth2App RBACResource = "oauth2_app" - ResourceOauth2AppCodeToken RBACResource = "oauth2_app_code_token" - ResourceOauth2AppSecret RBACResource = "oauth2_app_secret" - ResourceOrganization RBACResource = "organization" - ResourceOrganizationMember RBACResource = "organization_member" - ResourceProvisionerDaemon RBACResource = "provisioner_daemon" - ResourceProvisionerJobs RBACResource = "provisioner_jobs" - ResourceProvisionerKeys RBACResource = "provisioner_keys" - ResourceReplicas RBACResource = "replicas" - ResourceSystem RBACResource = "system" - ResourceTailnetCoordinator RBACResource = "tailnet_coordinator" - ResourceTemplate RBACResource = "template" - ResourceUser RBACResource = "user" - ResourceWorkspace RBACResource = "workspace" - ResourceWorkspaceDormant RBACResource = "workspace_dormant" - ResourceWorkspaceProxy RBACResource = "workspace_proxy" + ResourceWildcard RBACResource = "*" + ResourceApiKey RBACResource = "api_key" + ResourceAssignOrgRole RBACResource = "assign_org_role" + ResourceAssignRole RBACResource = "assign_role" + ResourceAuditLog RBACResource = "audit_log" + ResourceCryptoKey RBACResource = "crypto_key" + ResourceDebugInfo RBACResource = "debug_info" + ResourceDeploymentConfig RBACResource = "deployment_config" + ResourceDeploymentStats RBACResource = "deployment_stats" + ResourceFile RBACResource = "file" + ResourceGroup RBACResource = "group" + ResourceGroupMember RBACResource = "group_member" + ResourceIdpsyncSettings RBACResource = "idpsync_settings" + ResourceLicense RBACResource = "license" + ResourceNotificationMessage RBACResource = "notification_message" + ResourceNotificationPreference RBACResource = "notification_preference" + ResourceNotificationTemplate RBACResource = "notification_template" + ResourceOauth2App RBACResource = "oauth2_app" + ResourceOauth2AppCodeToken RBACResource = "oauth2_app_code_token" + ResourceOauth2AppSecret RBACResource = "oauth2_app_secret" + ResourceOrganization RBACResource = "organization" + ResourceOrganizationMember RBACResource = "organization_member" + ResourceProvisionerDaemon RBACResource = "provisioner_daemon" + ResourceProvisionerJobs RBACResource = "provisioner_jobs" + ResourceProvisionerKeys RBACResource = "provisioner_keys" + ResourceReplicas RBACResource = "replicas" + ResourceSystem RBACResource = "system" + ResourceTailnetCoordinator RBACResource = "tailnet_coordinator" + ResourceTemplate RBACResource = "template" + ResourceUser RBACResource = "user" + ResourceWorkspace RBACResource = "workspace" + ResourceWorkspaceAgentResourceMonitor RBACResource = "workspace_agent_resource_monitor" + ResourceWorkspaceDormant RBACResource = "workspace_dormant" + ResourceWorkspaceProxy RBACResource = "workspace_proxy" ) type RBACAction string @@ -60,37 +61,38 @@ const ( // RBACResourceActions is the mapping of resources to which actions are valid for // said resource type. var RBACResourceActions = map[RBACResource][]RBACAction{ - ResourceWildcard: {}, - ResourceApiKey: {ActionCreate, ActionDelete, ActionRead, ActionUpdate}, - ResourceAssignOrgRole: {ActionAssign, ActionCreate, ActionDelete, ActionRead, ActionUpdate}, - ResourceAssignRole: {ActionAssign, ActionCreate, ActionDelete, ActionRead, ActionUpdate}, - ResourceAuditLog: {ActionCreate, ActionRead}, - ResourceCryptoKey: {ActionCreate, ActionDelete, ActionRead, ActionUpdate}, - ResourceDebugInfo: {ActionRead}, - ResourceDeploymentConfig: {ActionRead, ActionUpdate}, - ResourceDeploymentStats: {ActionRead}, - ResourceFile: {ActionCreate, ActionRead}, - ResourceGroup: {ActionCreate, ActionDelete, ActionRead, ActionUpdate}, - ResourceGroupMember: {ActionRead}, - ResourceIdpsyncSettings: {ActionRead, ActionUpdate}, - ResourceLicense: {ActionCreate, ActionDelete, ActionRead}, - ResourceNotificationMessage: {ActionCreate, ActionDelete, ActionRead, ActionUpdate}, - ResourceNotificationPreference: {ActionRead, ActionUpdate}, - ResourceNotificationTemplate: {ActionRead, ActionUpdate}, - ResourceOauth2App: {ActionCreate, ActionDelete, ActionRead, ActionUpdate}, - ResourceOauth2AppCodeToken: {ActionCreate, ActionDelete, ActionRead}, - ResourceOauth2AppSecret: {ActionCreate, ActionDelete, ActionRead, ActionUpdate}, - ResourceOrganization: {ActionCreate, ActionDelete, ActionRead, ActionUpdate}, - ResourceOrganizationMember: {ActionCreate, ActionDelete, ActionRead, ActionUpdate}, - ResourceProvisionerDaemon: {ActionCreate, ActionDelete, ActionRead, ActionUpdate}, - ResourceProvisionerJobs: {ActionRead}, - ResourceProvisionerKeys: {ActionCreate, ActionDelete, ActionRead}, - ResourceReplicas: {ActionRead}, - ResourceSystem: {ActionCreate, ActionDelete, ActionRead, ActionUpdate}, - ResourceTailnetCoordinator: {ActionCreate, ActionDelete, ActionRead, ActionUpdate}, - ResourceTemplate: {ActionCreate, ActionDelete, ActionRead, ActionUpdate, ActionUse, ActionViewInsights}, - ResourceUser: {ActionCreate, ActionDelete, ActionRead, ActionReadPersonal, ActionUpdate, ActionUpdatePersonal}, - ResourceWorkspace: {ActionApplicationConnect, ActionCreate, ActionDelete, ActionRead, ActionSSH, ActionWorkspaceStart, ActionWorkspaceStop, ActionUpdate}, - ResourceWorkspaceDormant: {ActionApplicationConnect, ActionCreate, ActionDelete, ActionRead, ActionSSH, ActionWorkspaceStart, ActionWorkspaceStop, ActionUpdate}, - ResourceWorkspaceProxy: {ActionCreate, ActionDelete, ActionRead, ActionUpdate}, + ResourceWildcard: {}, + ResourceApiKey: {ActionCreate, ActionDelete, ActionRead, ActionUpdate}, + ResourceAssignOrgRole: {ActionAssign, ActionCreate, ActionDelete, ActionRead, ActionUpdate}, + ResourceAssignRole: {ActionAssign, ActionCreate, ActionDelete, ActionRead, ActionUpdate}, + ResourceAuditLog: {ActionCreate, ActionRead}, + ResourceCryptoKey: {ActionCreate, ActionDelete, ActionRead, ActionUpdate}, + ResourceDebugInfo: {ActionRead}, + ResourceDeploymentConfig: {ActionRead, ActionUpdate}, + ResourceDeploymentStats: {ActionRead}, + ResourceFile: {ActionCreate, ActionRead}, + ResourceGroup: {ActionCreate, ActionDelete, ActionRead, ActionUpdate}, + ResourceGroupMember: {ActionRead}, + ResourceIdpsyncSettings: {ActionRead, ActionUpdate}, + ResourceLicense: {ActionCreate, ActionDelete, ActionRead}, + ResourceNotificationMessage: {ActionCreate, ActionDelete, ActionRead, ActionUpdate}, + ResourceNotificationPreference: {ActionRead, ActionUpdate}, + ResourceNotificationTemplate: {ActionRead, ActionUpdate}, + ResourceOauth2App: {ActionCreate, ActionDelete, ActionRead, ActionUpdate}, + ResourceOauth2AppCodeToken: {ActionCreate, ActionDelete, ActionRead}, + ResourceOauth2AppSecret: {ActionCreate, ActionDelete, ActionRead, ActionUpdate}, + ResourceOrganization: {ActionCreate, ActionDelete, ActionRead, ActionUpdate}, + ResourceOrganizationMember: {ActionCreate, ActionDelete, ActionRead, ActionUpdate}, + ResourceProvisionerDaemon: {ActionCreate, ActionDelete, ActionRead, ActionUpdate}, + ResourceProvisionerJobs: {ActionRead}, + ResourceProvisionerKeys: {ActionCreate, ActionDelete, ActionRead}, + ResourceReplicas: {ActionRead}, + ResourceSystem: {ActionCreate, ActionDelete, ActionRead, ActionUpdate}, + ResourceTailnetCoordinator: {ActionCreate, ActionDelete, ActionRead, ActionUpdate}, + ResourceTemplate: {ActionCreate, ActionDelete, ActionRead, ActionUpdate, ActionUse, ActionViewInsights}, + ResourceUser: {ActionCreate, ActionDelete, ActionRead, ActionReadPersonal, ActionUpdate, ActionUpdatePersonal}, + ResourceWorkspace: {ActionApplicationConnect, ActionCreate, ActionDelete, ActionRead, ActionSSH, ActionWorkspaceStart, ActionWorkspaceStop, ActionUpdate}, + ResourceWorkspaceAgentResourceMonitor: {ActionCreate, ActionRead}, + ResourceWorkspaceDormant: {ActionApplicationConnect, ActionCreate, ActionDelete, ActionRead, ActionSSH, ActionWorkspaceStart, ActionWorkspaceStop, ActionUpdate}, + ResourceWorkspaceProxy: {ActionCreate, ActionDelete, ActionRead, ActionUpdate}, } diff --git a/docs/reference/api/members.md b/docs/reference/api/members.md index efe76a2eda58e..a3a38457c6631 100644 --- a/docs/reference/api/members.md +++ b/docs/reference/api/members.md @@ -164,54 +164,55 @@ Status Code **200** #### Enumerated Values -| Property | Value | -|-----------------|---------------------------| -| `action` | `application_connect` | -| `action` | `assign` | -| `action` | `create` | -| `action` | `delete` | -| `action` | `read` | -| `action` | `read_personal` | -| `action` | `ssh` | -| `action` | `update` | -| `action` | `update_personal` | -| `action` | `use` | -| `action` | `view_insights` | -| `action` | `start` | -| `action` | `stop` | -| `resource_type` | `*` | -| `resource_type` | `api_key` | -| `resource_type` | `assign_org_role` | -| `resource_type` | `assign_role` | -| `resource_type` | `audit_log` | -| `resource_type` | `crypto_key` | -| `resource_type` | `debug_info` | -| `resource_type` | `deployment_config` | -| `resource_type` | `deployment_stats` | -| `resource_type` | `file` | -| `resource_type` | `group` | -| `resource_type` | `group_member` | -| `resource_type` | `idpsync_settings` | -| `resource_type` | `license` | -| `resource_type` | `notification_message` | -| `resource_type` | `notification_preference` | -| `resource_type` | `notification_template` | -| `resource_type` | `oauth2_app` | -| `resource_type` | `oauth2_app_code_token` | -| `resource_type` | `oauth2_app_secret` | -| `resource_type` | `organization` | -| `resource_type` | `organization_member` | -| `resource_type` | `provisioner_daemon` | -| `resource_type` | `provisioner_jobs` | -| `resource_type` | `provisioner_keys` | -| `resource_type` | `replicas` | -| `resource_type` | `system` | -| `resource_type` | `tailnet_coordinator` | -| `resource_type` | `template` | -| `resource_type` | `user` | -| `resource_type` | `workspace` | -| `resource_type` | `workspace_dormant` | -| `resource_type` | `workspace_proxy` | +| Property | Value | +|-----------------|------------------------------------| +| `action` | `application_connect` | +| `action` | `assign` | +| `action` | `create` | +| `action` | `delete` | +| `action` | `read` | +| `action` | `read_personal` | +| `action` | `ssh` | +| `action` | `update` | +| `action` | `update_personal` | +| `action` | `use` | +| `action` | `view_insights` | +| `action` | `start` | +| `action` | `stop` | +| `resource_type` | `*` | +| `resource_type` | `api_key` | +| `resource_type` | `assign_org_role` | +| `resource_type` | `assign_role` | +| `resource_type` | `audit_log` | +| `resource_type` | `crypto_key` | +| `resource_type` | `debug_info` | +| `resource_type` | `deployment_config` | +| `resource_type` | `deployment_stats` | +| `resource_type` | `file` | +| `resource_type` | `group` | +| `resource_type` | `group_member` | +| `resource_type` | `idpsync_settings` | +| `resource_type` | `license` | +| `resource_type` | `notification_message` | +| `resource_type` | `notification_preference` | +| `resource_type` | `notification_template` | +| `resource_type` | `oauth2_app` | +| `resource_type` | `oauth2_app_code_token` | +| `resource_type` | `oauth2_app_secret` | +| `resource_type` | `organization` | +| `resource_type` | `organization_member` | +| `resource_type` | `provisioner_daemon` | +| `resource_type` | `provisioner_jobs` | +| `resource_type` | `provisioner_keys` | +| `resource_type` | `replicas` | +| `resource_type` | `system` | +| `resource_type` | `tailnet_coordinator` | +| `resource_type` | `template` | +| `resource_type` | `user` | +| `resource_type` | `workspace` | +| `resource_type` | `workspace_agent_resource_monitor` | +| `resource_type` | `workspace_dormant` | +| `resource_type` | `workspace_proxy` | To perform this operation, you must be authenticated. [Learn more](authentication.md). @@ -326,54 +327,55 @@ Status Code **200** #### Enumerated Values -| Property | Value | -|-----------------|---------------------------| -| `action` | `application_connect` | -| `action` | `assign` | -| `action` | `create` | -| `action` | `delete` | -| `action` | `read` | -| `action` | `read_personal` | -| `action` | `ssh` | -| `action` | `update` | -| `action` | `update_personal` | -| `action` | `use` | -| `action` | `view_insights` | -| `action` | `start` | -| `action` | `stop` | -| `resource_type` | `*` | -| `resource_type` | `api_key` | -| `resource_type` | `assign_org_role` | -| `resource_type` | `assign_role` | -| `resource_type` | `audit_log` | -| `resource_type` | `crypto_key` | -| `resource_type` | `debug_info` | -| `resource_type` | `deployment_config` | -| `resource_type` | `deployment_stats` | -| `resource_type` | `file` | -| `resource_type` | `group` | -| `resource_type` | `group_member` | -| `resource_type` | `idpsync_settings` | -| `resource_type` | `license` | -| `resource_type` | `notification_message` | -| `resource_type` | `notification_preference` | -| `resource_type` | `notification_template` | -| `resource_type` | `oauth2_app` | -| `resource_type` | `oauth2_app_code_token` | -| `resource_type` | `oauth2_app_secret` | -| `resource_type` | `organization` | -| `resource_type` | `organization_member` | -| `resource_type` | `provisioner_daemon` | -| `resource_type` | `provisioner_jobs` | -| `resource_type` | `provisioner_keys` | -| `resource_type` | `replicas` | -| `resource_type` | `system` | -| `resource_type` | `tailnet_coordinator` | -| `resource_type` | `template` | -| `resource_type` | `user` | -| `resource_type` | `workspace` | -| `resource_type` | `workspace_dormant` | -| `resource_type` | `workspace_proxy` | +| Property | Value | +|-----------------|------------------------------------| +| `action` | `application_connect` | +| `action` | `assign` | +| `action` | `create` | +| `action` | `delete` | +| `action` | `read` | +| `action` | `read_personal` | +| `action` | `ssh` | +| `action` | `update` | +| `action` | `update_personal` | +| `action` | `use` | +| `action` | `view_insights` | +| `action` | `start` | +| `action` | `stop` | +| `resource_type` | `*` | +| `resource_type` | `api_key` | +| `resource_type` | `assign_org_role` | +| `resource_type` | `assign_role` | +| `resource_type` | `audit_log` | +| `resource_type` | `crypto_key` | +| `resource_type` | `debug_info` | +| `resource_type` | `deployment_config` | +| `resource_type` | `deployment_stats` | +| `resource_type` | `file` | +| `resource_type` | `group` | +| `resource_type` | `group_member` | +| `resource_type` | `idpsync_settings` | +| `resource_type` | `license` | +| `resource_type` | `notification_message` | +| `resource_type` | `notification_preference` | +| `resource_type` | `notification_template` | +| `resource_type` | `oauth2_app` | +| `resource_type` | `oauth2_app_code_token` | +| `resource_type` | `oauth2_app_secret` | +| `resource_type` | `organization` | +| `resource_type` | `organization_member` | +| `resource_type` | `provisioner_daemon` | +| `resource_type` | `provisioner_jobs` | +| `resource_type` | `provisioner_keys` | +| `resource_type` | `replicas` | +| `resource_type` | `system` | +| `resource_type` | `tailnet_coordinator` | +| `resource_type` | `template` | +| `resource_type` | `user` | +| `resource_type` | `workspace` | +| `resource_type` | `workspace_agent_resource_monitor` | +| `resource_type` | `workspace_dormant` | +| `resource_type` | `workspace_proxy` | To perform this operation, you must be authenticated. [Learn more](authentication.md). @@ -488,54 +490,55 @@ Status Code **200** #### Enumerated Values -| Property | Value | -|-----------------|---------------------------| -| `action` | `application_connect` | -| `action` | `assign` | -| `action` | `create` | -| `action` | `delete` | -| `action` | `read` | -| `action` | `read_personal` | -| `action` | `ssh` | -| `action` | `update` | -| `action` | `update_personal` | -| `action` | `use` | -| `action` | `view_insights` | -| `action` | `start` | -| `action` | `stop` | -| `resource_type` | `*` | -| `resource_type` | `api_key` | -| `resource_type` | `assign_org_role` | -| `resource_type` | `assign_role` | -| `resource_type` | `audit_log` | -| `resource_type` | `crypto_key` | -| `resource_type` | `debug_info` | -| `resource_type` | `deployment_config` | -| `resource_type` | `deployment_stats` | -| `resource_type` | `file` | -| `resource_type` | `group` | -| `resource_type` | `group_member` | -| `resource_type` | `idpsync_settings` | -| `resource_type` | `license` | -| `resource_type` | `notification_message` | -| `resource_type` | `notification_preference` | -| `resource_type` | `notification_template` | -| `resource_type` | `oauth2_app` | -| `resource_type` | `oauth2_app_code_token` | -| `resource_type` | `oauth2_app_secret` | -| `resource_type` | `organization` | -| `resource_type` | `organization_member` | -| `resource_type` | `provisioner_daemon` | -| `resource_type` | `provisioner_jobs` | -| `resource_type` | `provisioner_keys` | -| `resource_type` | `replicas` | -| `resource_type` | `system` | -| `resource_type` | `tailnet_coordinator` | -| `resource_type` | `template` | -| `resource_type` | `user` | -| `resource_type` | `workspace` | -| `resource_type` | `workspace_dormant` | -| `resource_type` | `workspace_proxy` | +| Property | Value | +|-----------------|------------------------------------| +| `action` | `application_connect` | +| `action` | `assign` | +| `action` | `create` | +| `action` | `delete` | +| `action` | `read` | +| `action` | `read_personal` | +| `action` | `ssh` | +| `action` | `update` | +| `action` | `update_personal` | +| `action` | `use` | +| `action` | `view_insights` | +| `action` | `start` | +| `action` | `stop` | +| `resource_type` | `*` | +| `resource_type` | `api_key` | +| `resource_type` | `assign_org_role` | +| `resource_type` | `assign_role` | +| `resource_type` | `audit_log` | +| `resource_type` | `crypto_key` | +| `resource_type` | `debug_info` | +| `resource_type` | `deployment_config` | +| `resource_type` | `deployment_stats` | +| `resource_type` | `file` | +| `resource_type` | `group` | +| `resource_type` | `group_member` | +| `resource_type` | `idpsync_settings` | +| `resource_type` | `license` | +| `resource_type` | `notification_message` | +| `resource_type` | `notification_preference` | +| `resource_type` | `notification_template` | +| `resource_type` | `oauth2_app` | +| `resource_type` | `oauth2_app_code_token` | +| `resource_type` | `oauth2_app_secret` | +| `resource_type` | `organization` | +| `resource_type` | `organization_member` | +| `resource_type` | `provisioner_daemon` | +| `resource_type` | `provisioner_jobs` | +| `resource_type` | `provisioner_keys` | +| `resource_type` | `replicas` | +| `resource_type` | `system` | +| `resource_type` | `tailnet_coordinator` | +| `resource_type` | `template` | +| `resource_type` | `user` | +| `resource_type` | `workspace` | +| `resource_type` | `workspace_agent_resource_monitor` | +| `resource_type` | `workspace_dormant` | +| `resource_type` | `workspace_proxy` | To perform this operation, you must be authenticated. [Learn more](authentication.md). @@ -619,54 +622,55 @@ Status Code **200** #### Enumerated Values -| Property | Value | -|-----------------|---------------------------| -| `action` | `application_connect` | -| `action` | `assign` | -| `action` | `create` | -| `action` | `delete` | -| `action` | `read` | -| `action` | `read_personal` | -| `action` | `ssh` | -| `action` | `update` | -| `action` | `update_personal` | -| `action` | `use` | -| `action` | `view_insights` | -| `action` | `start` | -| `action` | `stop` | -| `resource_type` | `*` | -| `resource_type` | `api_key` | -| `resource_type` | `assign_org_role` | -| `resource_type` | `assign_role` | -| `resource_type` | `audit_log` | -| `resource_type` | `crypto_key` | -| `resource_type` | `debug_info` | -| `resource_type` | `deployment_config` | -| `resource_type` | `deployment_stats` | -| `resource_type` | `file` | -| `resource_type` | `group` | -| `resource_type` | `group_member` | -| `resource_type` | `idpsync_settings` | -| `resource_type` | `license` | -| `resource_type` | `notification_message` | -| `resource_type` | `notification_preference` | -| `resource_type` | `notification_template` | -| `resource_type` | `oauth2_app` | -| `resource_type` | `oauth2_app_code_token` | -| `resource_type` | `oauth2_app_secret` | -| `resource_type` | `organization` | -| `resource_type` | `organization_member` | -| `resource_type` | `provisioner_daemon` | -| `resource_type` | `provisioner_jobs` | -| `resource_type` | `provisioner_keys` | -| `resource_type` | `replicas` | -| `resource_type` | `system` | -| `resource_type` | `tailnet_coordinator` | -| `resource_type` | `template` | -| `resource_type` | `user` | -| `resource_type` | `workspace` | -| `resource_type` | `workspace_dormant` | -| `resource_type` | `workspace_proxy` | +| Property | Value | +|-----------------|------------------------------------| +| `action` | `application_connect` | +| `action` | `assign` | +| `action` | `create` | +| `action` | `delete` | +| `action` | `read` | +| `action` | `read_personal` | +| `action` | `ssh` | +| `action` | `update` | +| `action` | `update_personal` | +| `action` | `use` | +| `action` | `view_insights` | +| `action` | `start` | +| `action` | `stop` | +| `resource_type` | `*` | +| `resource_type` | `api_key` | +| `resource_type` | `assign_org_role` | +| `resource_type` | `assign_role` | +| `resource_type` | `audit_log` | +| `resource_type` | `crypto_key` | +| `resource_type` | `debug_info` | +| `resource_type` | `deployment_config` | +| `resource_type` | `deployment_stats` | +| `resource_type` | `file` | +| `resource_type` | `group` | +| `resource_type` | `group_member` | +| `resource_type` | `idpsync_settings` | +| `resource_type` | `license` | +| `resource_type` | `notification_message` | +| `resource_type` | `notification_preference` | +| `resource_type` | `notification_template` | +| `resource_type` | `oauth2_app` | +| `resource_type` | `oauth2_app_code_token` | +| `resource_type` | `oauth2_app_secret` | +| `resource_type` | `organization` | +| `resource_type` | `organization_member` | +| `resource_type` | `provisioner_daemon` | +| `resource_type` | `provisioner_jobs` | +| `resource_type` | `provisioner_keys` | +| `resource_type` | `replicas` | +| `resource_type` | `system` | +| `resource_type` | `tailnet_coordinator` | +| `resource_type` | `template` | +| `resource_type` | `user` | +| `resource_type` | `workspace` | +| `resource_type` | `workspace_agent_resource_monitor` | +| `resource_type` | `workspace_dormant` | +| `resource_type` | `workspace_proxy` | To perform this operation, you must be authenticated. [Learn more](authentication.md). @@ -882,53 +886,54 @@ Status Code **200** #### Enumerated Values -| Property | Value | -|-----------------|---------------------------| -| `action` | `application_connect` | -| `action` | `assign` | -| `action` | `create` | -| `action` | `delete` | -| `action` | `read` | -| `action` | `read_personal` | -| `action` | `ssh` | -| `action` | `update` | -| `action` | `update_personal` | -| `action` | `use` | -| `action` | `view_insights` | -| `action` | `start` | -| `action` | `stop` | -| `resource_type` | `*` | -| `resource_type` | `api_key` | -| `resource_type` | `assign_org_role` | -| `resource_type` | `assign_role` | -| `resource_type` | `audit_log` | -| `resource_type` | `crypto_key` | -| `resource_type` | `debug_info` | -| `resource_type` | `deployment_config` | -| `resource_type` | `deployment_stats` | -| `resource_type` | `file` | -| `resource_type` | `group` | -| `resource_type` | `group_member` | -| `resource_type` | `idpsync_settings` | -| `resource_type` | `license` | -| `resource_type` | `notification_message` | -| `resource_type` | `notification_preference` | -| `resource_type` | `notification_template` | -| `resource_type` | `oauth2_app` | -| `resource_type` | `oauth2_app_code_token` | -| `resource_type` | `oauth2_app_secret` | -| `resource_type` | `organization` | -| `resource_type` | `organization_member` | -| `resource_type` | `provisioner_daemon` | -| `resource_type` | `provisioner_jobs` | -| `resource_type` | `provisioner_keys` | -| `resource_type` | `replicas` | -| `resource_type` | `system` | -| `resource_type` | `tailnet_coordinator` | -| `resource_type` | `template` | -| `resource_type` | `user` | -| `resource_type` | `workspace` | -| `resource_type` | `workspace_dormant` | -| `resource_type` | `workspace_proxy` | +| Property | Value | +|-----------------|------------------------------------| +| `action` | `application_connect` | +| `action` | `assign` | +| `action` | `create` | +| `action` | `delete` | +| `action` | `read` | +| `action` | `read_personal` | +| `action` | `ssh` | +| `action` | `update` | +| `action` | `update_personal` | +| `action` | `use` | +| `action` | `view_insights` | +| `action` | `start` | +| `action` | `stop` | +| `resource_type` | `*` | +| `resource_type` | `api_key` | +| `resource_type` | `assign_org_role` | +| `resource_type` | `assign_role` | +| `resource_type` | `audit_log` | +| `resource_type` | `crypto_key` | +| `resource_type` | `debug_info` | +| `resource_type` | `deployment_config` | +| `resource_type` | `deployment_stats` | +| `resource_type` | `file` | +| `resource_type` | `group` | +| `resource_type` | `group_member` | +| `resource_type` | `idpsync_settings` | +| `resource_type` | `license` | +| `resource_type` | `notification_message` | +| `resource_type` | `notification_preference` | +| `resource_type` | `notification_template` | +| `resource_type` | `oauth2_app` | +| `resource_type` | `oauth2_app_code_token` | +| `resource_type` | `oauth2_app_secret` | +| `resource_type` | `organization` | +| `resource_type` | `organization_member` | +| `resource_type` | `provisioner_daemon` | +| `resource_type` | `provisioner_jobs` | +| `resource_type` | `provisioner_keys` | +| `resource_type` | `replicas` | +| `resource_type` | `system` | +| `resource_type` | `tailnet_coordinator` | +| `resource_type` | `template` | +| `resource_type` | `user` | +| `resource_type` | `workspace` | +| `resource_type` | `workspace_agent_resource_monitor` | +| `resource_type` | `workspace_dormant` | +| `resource_type` | `workspace_proxy` | To perform this operation, you must be authenticated. [Learn more](authentication.md). diff --git a/docs/reference/api/schemas.md b/docs/reference/api/schemas.md index 20ed37f81f7f7..1af6ac7285d04 100644 --- a/docs/reference/api/schemas.md +++ b/docs/reference/api/schemas.md @@ -4991,41 +4991,42 @@ Git clone makes use of this by parsing the URL from: 'Username for "https://gith #### Enumerated Values -| Value | -|---------------------------| -| `*` | -| `api_key` | -| `assign_org_role` | -| `assign_role` | -| `audit_log` | -| `crypto_key` | -| `debug_info` | -| `deployment_config` | -| `deployment_stats` | -| `file` | -| `group` | -| `group_member` | -| `idpsync_settings` | -| `license` | -| `notification_message` | -| `notification_preference` | -| `notification_template` | -| `oauth2_app` | -| `oauth2_app_code_token` | -| `oauth2_app_secret` | -| `organization` | -| `organization_member` | -| `provisioner_daemon` | -| `provisioner_jobs` | -| `provisioner_keys` | -| `replicas` | -| `system` | -| `tailnet_coordinator` | -| `template` | -| `user` | -| `workspace` | -| `workspace_dormant` | -| `workspace_proxy` | +| Value | +|------------------------------------| +| `*` | +| `api_key` | +| `assign_org_role` | +| `assign_role` | +| `audit_log` | +| `crypto_key` | +| `debug_info` | +| `deployment_config` | +| `deployment_stats` | +| `file` | +| `group` | +| `group_member` | +| `idpsync_settings` | +| `license` | +| `notification_message` | +| `notification_preference` | +| `notification_template` | +| `oauth2_app` | +| `oauth2_app_code_token` | +| `oauth2_app_secret` | +| `organization` | +| `organization_member` | +| `provisioner_daemon` | +| `provisioner_jobs` | +| `provisioner_keys` | +| `replicas` | +| `system` | +| `tailnet_coordinator` | +| `template` | +| `user` | +| `workspace` | +| `workspace_agent_resource_monitor` | +| `workspace_dormant` | +| `workspace_proxy` | ## codersdk.RateLimitConfig diff --git a/site/src/api/rbacresourcesGenerated.ts b/site/src/api/rbacresourcesGenerated.ts index 886f1b0239694..e557ceddbdda6 100644 --- a/site/src/api/rbacresourcesGenerated.ts +++ b/site/src/api/rbacresourcesGenerated.ts @@ -168,6 +168,10 @@ export const RBACResourceActions: Partial< stop: "allows stopping a workspace", update: "edit workspace settings (scheduling, permissions, parameters)", }, + workspace_agent_resource_monitor: { + create: "create workspace agent resource monitor", + read: "read workspace agent resource monitor", + }, workspace_dormant: { application_connect: "connect to workspace apps via browser", create: "create a new workspace", diff --git a/site/src/api/typesGenerated.ts b/site/src/api/typesGenerated.ts index de879ee23daa5..58375a98370a0 100644 --- a/site/src/api/typesGenerated.ts +++ b/site/src/api/typesGenerated.ts @@ -1848,6 +1848,7 @@ export type RBACResource = | "user" | "*" | "workspace" + | "workspace_agent_resource_monitor" | "workspace_dormant" | "workspace_proxy"; @@ -1883,6 +1884,7 @@ export const RBACResources: RBACResource[] = [ "user", "*", "workspace", + "workspace_agent_resource_monitor", "workspace_dormant", "workspace_proxy", ]; From c5a420198aeb32eec133ca768e14f464a968abc6 Mon Sep 17 00:00:00 2001 From: defelmnq Date: Thu, 13 Feb 2025 18:00:07 +0000 Subject: [PATCH 28/32] improve dbauthz for fetching --- coderd/database/dbauthz/dbauthz.go | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/coderd/database/dbauthz/dbauthz.go b/coderd/database/dbauthz/dbauthz.go index 297ce340b1190..daaf4d805ba08 100644 --- a/coderd/database/dbauthz/dbauthz.go +++ b/coderd/database/dbauthz/dbauthz.go @@ -1394,6 +1394,16 @@ func (q *querier) FavoriteWorkspace(ctx context.Context, id uuid.UUID) error { } func (q *querier) FetchMemoryResourceMonitorsByAgentID(ctx context.Context, agentID uuid.UUID) (database.WorkspaceAgentMemoryResourceMonitor, error) { + workspace, err := q.db.GetWorkspaceByAgentID(ctx, agentID) + if err != nil { + return database.WorkspaceAgentMemoryResourceMonitor{}, err + } + + err = q.authorizeContext(ctx, policy.ActionUpdate, workspace) + if err != nil { + return database.WorkspaceAgentMemoryResourceMonitor{}, err + } + return q.db.FetchMemoryResourceMonitorsByAgentID(ctx, agentID) } @@ -1405,6 +1415,16 @@ func (q *querier) FetchNewMessageMetadata(ctx context.Context, arg database.Fetc } func (q *querier) FetchVolumesResourceMonitorsByAgentID(ctx context.Context, agentID uuid.UUID) ([]database.WorkspaceAgentVolumeResourceMonitor, error) { + workspace, err := q.db.GetWorkspaceByAgentID(ctx, agentID) + if err != nil { + return nil, err + } + + err = q.authorizeContext(ctx, policy.ActionUpdate, workspace) + if err != nil { + return nil, err + } + return q.db.FetchVolumesResourceMonitorsByAgentID(ctx, agentID) } From 262a672d1566e91e6e4d54f5eaad3c80483d32df Mon Sep 17 00:00:00 2001 From: defelmnq Date: Thu, 13 Feb 2025 18:13:08 +0000 Subject: [PATCH 29/32] change dbauthz permissions --- coderd/database/dbauthz/dbauthz.go | 4 ++-- coderd/database/dbauthz/dbauthz_test.go | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/coderd/database/dbauthz/dbauthz.go b/coderd/database/dbauthz/dbauthz.go index daaf4d805ba08..8b95acc46b2ae 100644 --- a/coderd/database/dbauthz/dbauthz.go +++ b/coderd/database/dbauthz/dbauthz.go @@ -1399,7 +1399,7 @@ func (q *querier) FetchMemoryResourceMonitorsByAgentID(ctx context.Context, agen return database.WorkspaceAgentMemoryResourceMonitor{}, err } - err = q.authorizeContext(ctx, policy.ActionUpdate, workspace) + err = q.authorizeContext(ctx, policy.ActionRead, workspace) if err != nil { return database.WorkspaceAgentMemoryResourceMonitor{}, err } @@ -1420,7 +1420,7 @@ func (q *querier) FetchVolumesResourceMonitorsByAgentID(ctx context.Context, age return nil, err } - err = q.authorizeContext(ctx, policy.ActionUpdate, workspace) + err = q.authorizeContext(ctx, policy.ActionRead, workspace) if err != nil { return nil, err } diff --git a/coderd/database/dbauthz/dbauthz_test.go b/coderd/database/dbauthz/dbauthz_test.go index abfb9abfadac4..710acd7db3c78 100644 --- a/coderd/database/dbauthz/dbauthz_test.go +++ b/coderd/database/dbauthz/dbauthz_test.go @@ -4611,7 +4611,7 @@ func (s *MethodTestSuite) TestResourcesMonitor() { monitor, err := db.FetchMemoryResourceMonitorsByAgentID(context.Background(), agt.ID) require.NoError(s.T(), err) - check.Args(agt.ID).Asserts().Returns(monitor) + check.Args(agt.ID).Asserts(w, policy.ActionRead).Returns(monitor) })) s.Run("FetchVolumesResourceMonitorsByAgentID", s.Subtest(func(db database.Store, check *expects) { @@ -4652,6 +4652,6 @@ func (s *MethodTestSuite) TestResourcesMonitor() { monitors, err := db.FetchVolumesResourceMonitorsByAgentID(context.Background(), agt.ID) require.NoError(s.T(), err) - check.Args(agt.ID).Asserts().Returns(monitors) + check.Args(agt.ID).Asserts(w, policy.ActionRead).Returns(monitors) })) } From dbca96e032a8a386e057a29ed73ddf7996ca5431 Mon Sep 17 00:00:00 2001 From: defelmnq Date: Thu, 13 Feb 2025 21:14:56 +0000 Subject: [PATCH 30/32] finalise tests --- coderd/rbac/roles_test.go | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/coderd/rbac/roles_test.go b/coderd/rbac/roles_test.go index 6d42b1b05361c..9260fd56c0121 100644 --- a/coderd/rbac/roles_test.go +++ b/coderd/rbac/roles_test.go @@ -682,6 +682,21 @@ func TestRolePermissions(t *testing.T) { }, }, }, + { + Name: "ResourcesMonitoring", + Actions: []policy.Action{policy.ActionCreate, policy.ActionRead}, + Resource: rbac.ResourceWorkspaceAgentResourceMonitor, + AuthorizeMap: map[bool][]hasAuthSubjects{ + true: {owner}, + false: { + memberMe, orgMemberMe, otherOrgMember, + orgAdmin, otherOrgAdmin, + orgAuditor, otherOrgAuditor, + templateAdmin, orgTemplateAdmin, otherOrgTemplateAdmin, + userAdmin, orgUserAdmin, otherOrgUserAdmin, + }, + }, + }, { // Notification preferences are currently not organization-scoped // Any owner/admin may access any users' preferences From 3145eab53ff3f8604e0031571a6e1ce15a0b1397 Mon Sep 17 00:00:00 2001 From: defelmnq Date: Thu, 13 Feb 2025 22:25:44 +0000 Subject: [PATCH 31/32] fix comments from github --- agent/agent.go | 1 - agent/proto/resourcesmonitor/fetcher.go | 2 +- coderd/agentapi/api.go | 2 +- coderd/agentapi/resources_monitoring.go | 13 +++++------ coderd/rbac/roles_test.go | 30 ++++++++++++------------- tailnet/proto/version.go | 2 +- 6 files changed, 23 insertions(+), 27 deletions(-) diff --git a/agent/agent.go b/agent/agent.go index 6a26a7a3d8b87..7a9e4dba566db 100644 --- a/agent/agent.go +++ b/agent/agent.go @@ -789,7 +789,6 @@ func (a *agent) run() (retErr error) { connMan.startAgentAPI("report metadata", gracefulShutdownBehaviorStop, a.reportMetadata) // resources monitor can cease as soon as we start gracefully shutting down. - // The resources monitor is interesting when the workspace is running. connMan.startAgentAPI("resources monitor", gracefulShutdownBehaviorStop, func(ctx context.Context, aAPI proto.DRPCAgentClient24) error { logger := a.logger.Named("resources_monitor") clk := quartz.NewReal() diff --git a/agent/proto/resourcesmonitor/fetcher.go b/agent/proto/resourcesmonitor/fetcher.go index b8485ed13dcb7..495a249fe9198 100644 --- a/agent/proto/resourcesmonitor/fetcher.go +++ b/agent/proto/resourcesmonitor/fetcher.go @@ -25,7 +25,7 @@ func NewFetcher(f *clistat.Statter) *fetcher { func (f *fetcher) FetchMemory() (total int64, used int64, err error) { mem, err := f.HostMemory(clistat.PrefixDefault) if err != nil { - return 0, 0, err + return 0, 0, xerrors.Errorf("failed to fetch memory: %w", err) } if mem.Total == nil { diff --git a/coderd/agentapi/api.go b/coderd/agentapi/api.go index ed54bef6fbf46..7f9fda63cb98c 100644 --- a/coderd/agentapi/api.go +++ b/coderd/agentapi/api.go @@ -105,7 +105,7 @@ func New(opts Options) *API { api.ResourcesMonitoringAPI = &ResourcesMonitoringAPI{ Log: opts.Log, - AgentFn: api.agent, + AgentID: opts.AgentID, Database: opts.Database, } diff --git a/coderd/agentapi/resources_monitoring.go b/coderd/agentapi/resources_monitoring.go index 37cef8eb7d7a8..0bce9b5104be6 100644 --- a/coderd/agentapi/resources_monitoring.go +++ b/coderd/agentapi/resources_monitoring.go @@ -7,29 +7,26 @@ import ( "golang.org/x/xerrors" + "github.com/google/uuid" + "cdr.dev/slog" "github.com/coder/coder/v2/agent/proto" "github.com/coder/coder/v2/coderd/database" ) type ResourcesMonitoringAPI struct { - AgentFn func(context.Context) (database.WorkspaceAgent, error) + AgentID uuid.UUID Database database.Store Log slog.Logger } func (a *ResourcesMonitoringAPI) GetResourcesMonitoringConfiguration(ctx context.Context, _ *proto.GetResourcesMonitoringConfigurationRequest) (*proto.GetResourcesMonitoringConfigurationResponse, error) { - agent, err := a.AgentFn(ctx) - if err != nil { - return nil, xerrors.Errorf("failed to fetch agent: %w", err) - } - - memoryMonitor, memoryErr := a.Database.FetchMemoryResourceMonitorsByAgentID(ctx, agent.ID) + memoryMonitor, memoryErr := a.Database.FetchMemoryResourceMonitorsByAgentID(ctx, a.AgentID) if memoryErr != nil && !errors.Is(memoryErr, sql.ErrNoRows) { return nil, xerrors.Errorf("failed to fetch memory resource monitor: %w", memoryErr) } - volumeMonitors, err := a.Database.FetchVolumesResourceMonitorsByAgentID(ctx, agent.ID) + volumeMonitors, err := a.Database.FetchVolumesResourceMonitorsByAgentID(ctx, a.AgentID) if err != nil { return nil, xerrors.Errorf("failed to fetch volume resource monitors: %w", err) } diff --git a/coderd/rbac/roles_test.go b/coderd/rbac/roles_test.go index 9260fd56c0121..6db591d028454 100644 --- a/coderd/rbac/roles_test.go +++ b/coderd/rbac/roles_test.go @@ -682,21 +682,6 @@ func TestRolePermissions(t *testing.T) { }, }, }, - { - Name: "ResourcesMonitoring", - Actions: []policy.Action{policy.ActionCreate, policy.ActionRead}, - Resource: rbac.ResourceWorkspaceAgentResourceMonitor, - AuthorizeMap: map[bool][]hasAuthSubjects{ - true: {owner}, - false: { - memberMe, orgMemberMe, otherOrgMember, - orgAdmin, otherOrgAdmin, - orgAuditor, otherOrgAuditor, - templateAdmin, orgTemplateAdmin, otherOrgTemplateAdmin, - userAdmin, orgUserAdmin, otherOrgUserAdmin, - }, - }, - }, { // Notification preferences are currently not organization-scoped // Any owner/admin may access any users' preferences @@ -792,6 +777,21 @@ func TestRolePermissions(t *testing.T) { }, }, }, + { + Name: "ResourceMonitor", + Actions: []policy.Action{policy.ActionRead, policy.ActionCreate}, + Resource: rbac.ResourceWorkspaceAgentResourceMonitor, + AuthorizeMap: map[bool][]hasAuthSubjects{ + true: {owner}, + false: { + memberMe, orgMemberMe, otherOrgMember, + orgAdmin, otherOrgAdmin, + orgAuditor, otherOrgAuditor, + templateAdmin, orgTemplateAdmin, otherOrgTemplateAdmin, + userAdmin, orgUserAdmin, otherOrgUserAdmin, + }, + }, + }, } // We expect every permission to be tested above. diff --git a/tailnet/proto/version.go b/tailnet/proto/version.go index 8321efcc608e3..ea38518033704 100644 --- a/tailnet/proto/version.go +++ b/tailnet/proto/version.go @@ -40,7 +40,7 @@ import ( // ScriptCompleted, but be prepared to process "unsupported" errors.) // // API v2.4: -// - Shipped in Coder v2.19.0 +// - Shipped in Coder v2.{{placeholder}} // TODO Vincent: Replace with the correct version // - Added support for GetResourcesMonitoringConfiguration and // PushResourcesMonitoringUsage RPCs on the Agent API. const ( From 3bec3247b51659b2ed6bccaf76b275b78625cbfc Mon Sep 17 00:00:00 2001 From: defelmnq Date: Fri, 14 Feb 2025 08:49:57 +0000 Subject: [PATCH 32/32] add collectedAt --- agent/proto/resourcesmonitor/queue.go | 13 ++++++++++--- agent/proto/resourcesmonitor/resources_monitor.go | 3 ++- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/agent/proto/resourcesmonitor/queue.go b/agent/proto/resourcesmonitor/queue.go index 189b1ce8ab8ae..9f463509f2094 100644 --- a/agent/proto/resourcesmonitor/queue.go +++ b/agent/proto/resourcesmonitor/queue.go @@ -1,12 +1,17 @@ package resourcesmonitor import ( + "time" + + "google.golang.org/protobuf/types/known/timestamppb" + "github.com/coder/coder/v2/agent/proto" ) type Datapoint struct { - Memory *MemoryDatapoint - Volumes []*VolumeDatapoint + CollectedAt time.Time + Memory *MemoryDatapoint + Volumes []*VolumeDatapoint } type MemoryDatapoint struct { @@ -55,7 +60,9 @@ func (q *Queue) ItemsAsProto() []*proto.PushResourcesMonitoringUsageRequest_Data items := make([]*proto.PushResourcesMonitoringUsageRequest_Datapoint, 0, len(q.items)) for _, item := range q.items { - protoItem := &proto.PushResourcesMonitoringUsageRequest_Datapoint{} + protoItem := &proto.PushResourcesMonitoringUsageRequest_Datapoint{ + CollectedAt: timestamppb.New(item.CollectedAt), + } if item.Memory != nil { protoItem.Memory = &proto.PushResourcesMonitoringUsageRequest_Datapoint_MemoryUsage{ Total: item.Memory.Total, diff --git a/agent/proto/resourcesmonitor/resources_monitor.go b/agent/proto/resourcesmonitor/resources_monitor.go index d17d851fbd97f..7dea49614c072 100644 --- a/agent/proto/resourcesmonitor/resources_monitor.go +++ b/agent/proto/resourcesmonitor/resources_monitor.go @@ -37,7 +37,8 @@ type datapointsPusher interface { func (m *monitor) Start(ctx context.Context) error { m.clock.TickerFunc(ctx, time.Duration(m.config.Config.CollectionIntervalSeconds)*time.Second, func() error { datapoint := Datapoint{ - Volumes: make([]*VolumeDatapoint, 0, len(m.config.Volumes)), + CollectedAt: m.clock.Now(), + Volumes: make([]*VolumeDatapoint, 0, len(m.config.Volumes)), } if m.config.Memory != nil && m.config.Memory.Enabled { pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy