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 {