From d9a538071f91d1692faee6cc1eb8577bcbf3b022 Mon Sep 17 00:00:00 2001 From: Jingxiang Zhang Date: Wed, 24 Jun 2026 10:57:32 -0700 Subject: [PATCH] fix: include metric scrape interval in agent config Signed-off-by: Jingxiang Zhang --- internal/backendclient/types.go | 17 +++++++------- internal/config/config.go | 13 +++++++++++ internal/config/config_test.go | 8 +++++++ internal/enrollment/enrollment.go | 17 +++++++------- internal/inventory/mapper/backend.go | 17 +++++++------- internal/inventory/mapper/backend_test.go | 19 ++++++++------- internal/inventory/source/source_test.go | 18 ++++++++------- internal/inventory/types.go | 17 +++++++------- internal/server/server.go | 23 ++++++++----------- internal/validation/outbound/validator.go | 1 + .../validation/outbound/validator_test.go | 9 ++++++++ 11 files changed, 98 insertions(+), 61 deletions(-) diff --git a/internal/backendclient/types.go b/internal/backendclient/types.go index dfad2a6c..00420e1c 100644 --- a/internal/backendclient/types.go +++ b/internal/backendclient/types.go @@ -49,14 +49,15 @@ type NodeResources struct { } type AgentConfig struct { - TotalComponents int64 `json:"totalComponents"` - RetentionPeriodSeconds int64 `json:"retentionPeriodSeconds"` - EnabledComponents []string `json:"enabledComponents"` - DisabledComponents []string `json:"disabledComponents"` - InventoryEnabled bool `json:"inventoryEnabled"` - InventoryIntervalSeconds int64 `json:"inventoryIntervalSeconds"` - AttestationEnabled bool `json:"attestationEnabled"` - AttestationIntervalSeconds int64 `json:"attestationIntervalSeconds"` + TotalComponents int64 `json:"totalComponents"` + RetentionPeriodSeconds int64 `json:"retentionPeriodSeconds"` + MetricScrapeIntervalSeconds int64 `json:"metricScrapeIntervalSeconds"` + EnabledComponents []string `json:"enabledComponents"` + DisabledComponents []string `json:"disabledComponents"` + InventoryEnabled bool `json:"inventoryEnabled"` + InventoryIntervalSeconds int64 `json:"inventoryIntervalSeconds"` + AttestationEnabled bool `json:"attestationEnabled"` + AttestationIntervalSeconds int64 `json:"attestationIntervalSeconds"` } type CPUInfo struct { diff --git a/internal/config/config.go b/internal/config/config.go index 015aa435..2c1f45dc 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -345,6 +345,19 @@ func (config *Config) AttestationLoopAgentConfig() (enabled bool, intervalSecond return config.Attestation.Enabled, int64(config.Attestation.Interval.Seconds()) } +// HealthCheckInterval returns the resolved component health-check interval. +func (config *Config) HealthCheckInterval() time.Duration { + if config == nil || config.HealthExporter == nil || config.HealthExporter.HealthCheckInterval.Duration <= 0 { + return time.Minute + } + return config.HealthExporter.HealthCheckInterval.Duration +} + +// MetricScrapeIntervalSeconds returns the resolved metric scrape interval stored in inventory. +func (config *Config) MetricScrapeIntervalSeconds() int64 { + return int64(config.HealthCheckInterval().Seconds()) +} + // getComponentLists computes enabled/disabled lists from config rules against all available components. func (config *Config) getComponentLists(allComponentNames []string) (enabled, disabled []string) { enabled, disabled = []string{}, []string{} diff --git a/internal/config/config_test.go b/internal/config/config_test.go index c9503018..b4adc884 100644 --- a/internal/config/config_test.go +++ b/internal/config/config_test.go @@ -881,6 +881,9 @@ func TestInventoryAgentConfig(t *testing.T) { APIVersion: "v1", RetentionPeriod: metav1.Duration{Duration: 24 * time.Hour}, Components: []string{"*", "-memory", "-disk"}, + HealthExporter: &HealthExporterConfig{ + HealthCheckInterval: metav1.Duration{Duration: 30 * time.Second}, + }, Inventory: &InventoryConfig{ Enabled: true, Interval: metav1.Duration{Duration: time.Hour}, @@ -903,4 +906,9 @@ func TestInventoryAgentConfig(t *testing.T) { attestationEnabled, attestationIntervalSeconds := cfg.AttestationLoopAgentConfig() assert.True(t, attestationEnabled) assert.Equal(t, int64(86400), attestationIntervalSeconds) + + assert.Equal(t, 30*time.Second, cfg.HealthCheckInterval()) + assert.Equal(t, int64(30), cfg.MetricScrapeIntervalSeconds()) + assert.Equal(t, time.Minute, (*Config)(nil).HealthCheckInterval()) + assert.Equal(t, int64(60), (*Config)(nil).MetricScrapeIntervalSeconds()) } diff --git a/internal/enrollment/enrollment.go b/internal/enrollment/enrollment.go index 77ce9f1b..682494f9 100644 --- a/internal/enrollment/enrollment.go +++ b/internal/enrollment/enrollment.go @@ -219,14 +219,15 @@ func syncInventoryOnce(ctx context.Context, cfg *config.Config) error { return machineinfo.GetMachineInfo(nvmlInstance) }), &inventory.AgentConfig{ - TotalComponents: int64(len(allComponents)), - RetentionPeriodSeconds: retentionPeriodSeconds, - EnabledComponents: enabledComponents, - DisabledComponents: disabledComponents, - InventoryEnabled: inventoryEnabled, - InventoryIntervalSeconds: inventoryIntervalSeconds, - AttestationEnabled: attestationEnabled, - AttestationIntervalSeconds: attestationIntervalSeconds, + TotalComponents: int64(len(allComponents)), + RetentionPeriodSeconds: retentionPeriodSeconds, + MetricScrapeIntervalSeconds: cfg.MetricScrapeIntervalSeconds(), + EnabledComponents: enabledComponents, + DisabledComponents: disabledComponents, + InventoryEnabled: inventoryEnabled, + InventoryIntervalSeconds: inventoryIntervalSeconds, + AttestationEnabled: attestationEnabled, + AttestationIntervalSeconds: attestationIntervalSeconds, }, ) manager := inventory.NewManager(src, sink, inventory.InventoryConfig{}) diff --git a/internal/inventory/mapper/backend.go b/internal/inventory/mapper/backend.go index c197a5ed..b0603e3a 100644 --- a/internal/inventory/mapper/backend.go +++ b/internal/inventory/mapper/backend.go @@ -75,14 +75,15 @@ func ToNodeUpsertRequest(s *inventory.Snapshot) *backendclient.NodeUpsertRequest return &backendclient.NodeUpsertRequest{ Hostname: s.Hostname, AgentConfig: backendclient.AgentConfig{ - TotalComponents: s.AgentConfig.TotalComponents, - RetentionPeriodSeconds: s.AgentConfig.RetentionPeriodSeconds, - EnabledComponents: cloneStringSlice(s.AgentConfig.EnabledComponents), - DisabledComponents: cloneStringSlice(s.AgentConfig.DisabledComponents), - InventoryEnabled: s.AgentConfig.InventoryEnabled, - InventoryIntervalSeconds: s.AgentConfig.InventoryIntervalSeconds, - AttestationEnabled: s.AgentConfig.AttestationEnabled, - AttestationIntervalSeconds: s.AgentConfig.AttestationIntervalSeconds, + TotalComponents: s.AgentConfig.TotalComponents, + RetentionPeriodSeconds: s.AgentConfig.RetentionPeriodSeconds, + MetricScrapeIntervalSeconds: s.AgentConfig.MetricScrapeIntervalSeconds, + EnabledComponents: cloneStringSlice(s.AgentConfig.EnabledComponents), + DisabledComponents: cloneStringSlice(s.AgentConfig.DisabledComponents), + InventoryEnabled: s.AgentConfig.InventoryEnabled, + InventoryIntervalSeconds: s.AgentConfig.InventoryIntervalSeconds, + AttestationEnabled: s.AgentConfig.AttestationEnabled, + AttestationIntervalSeconds: s.AgentConfig.AttestationIntervalSeconds, }, MachineID: s.MachineID, SystemUUID: s.SystemUUID, diff --git a/internal/inventory/mapper/backend_test.go b/internal/inventory/mapper/backend_test.go index 5328990e..676c77f8 100644 --- a/internal/inventory/mapper/backend_test.go +++ b/internal/inventory/mapper/backend_test.go @@ -38,6 +38,7 @@ func TestToNodeUpsertRequestAgentConfigJSONIncludesZeroValues(t *testing.T) { require.JSONEq(t, `{ "totalComponents": 0, "retentionPeriodSeconds": 0, + "metricScrapeIntervalSeconds": 0, "enabledComponents": [], "disabledComponents": [], "inventoryEnabled": false, @@ -65,14 +66,15 @@ func TestToNodeUpsertRequest(t *testing.T) { ContainerRuntimeVersion: "containerd://1.7.13", NetPrivateIP: "10.0.0.10", AgentConfig: inventory.AgentConfig{ - TotalComponents: 30, - RetentionPeriodSeconds: 86400, - EnabledComponents: []string{"cpu", "gpu"}, - DisabledComponents: []string{"disk"}, - InventoryEnabled: true, - InventoryIntervalSeconds: 3600, - AttestationEnabled: true, - AttestationIntervalSeconds: 86400, + TotalComponents: 30, + RetentionPeriodSeconds: 86400, + MetricScrapeIntervalSeconds: 60, + EnabledComponents: []string{"cpu", "gpu"}, + DisabledComponents: []string{"disk"}, + InventoryEnabled: true, + InventoryIntervalSeconds: 3600, + AttestationEnabled: true, + AttestationIntervalSeconds: 86400, }, Resources: inventory.Resources{ CPUInfo: inventory.CPUInfo{ @@ -130,6 +132,7 @@ func TestToNodeUpsertRequest(t *testing.T) { require.Equal(t, bootTime.UTC(), *req.Uptime) require.Equal(t, int64(30), req.AgentConfig.TotalComponents) require.Equal(t, int64(86400), req.AgentConfig.RetentionPeriodSeconds) + require.Equal(t, int64(60), req.AgentConfig.MetricScrapeIntervalSeconds) require.Equal(t, []string{"cpu", "gpu"}, req.AgentConfig.EnabledComponents) require.Equal(t, []string{"disk"}, req.AgentConfig.DisabledComponents) require.True(t, req.AgentConfig.InventoryEnabled) diff --git a/internal/inventory/source/source_test.go b/internal/inventory/source/source_test.go index 3b857214..6bb6028e 100644 --- a/internal/inventory/source/source_test.go +++ b/internal/inventory/source/source_test.go @@ -129,14 +129,15 @@ func TestMachineInfoSourceCollectWithAgentConfig(t *testing.T) { }, }, &inventory.AgentConfig{ - TotalComponents: 42, - RetentionPeriodSeconds: 86400, - EnabledComponents: []string{"cpu", "gpu"}, - DisabledComponents: []string{"disk"}, - InventoryEnabled: true, - InventoryIntervalSeconds: 3600, - AttestationEnabled: true, - AttestationIntervalSeconds: 86400, + TotalComponents: 42, + RetentionPeriodSeconds: 86400, + MetricScrapeIntervalSeconds: 60, + EnabledComponents: []string{"cpu", "gpu"}, + DisabledComponents: []string{"disk"}, + InventoryEnabled: true, + InventoryIntervalSeconds: 3600, + AttestationEnabled: true, + AttestationIntervalSeconds: 86400, }, ) @@ -146,6 +147,7 @@ func TestMachineInfoSourceCollectWithAgentConfig(t *testing.T) { require.Equal(t, "machine-id", snap.MachineID) require.Equal(t, int64(42), snap.AgentConfig.TotalComponents) require.Equal(t, int64(86400), snap.AgentConfig.RetentionPeriodSeconds) + require.Equal(t, int64(60), snap.AgentConfig.MetricScrapeIntervalSeconds) require.Equal(t, []string{"cpu", "gpu"}, snap.AgentConfig.EnabledComponents) require.Equal(t, []string{"disk"}, snap.AgentConfig.DisabledComponents) require.True(t, snap.AgentConfig.InventoryEnabled) diff --git a/internal/inventory/types.go b/internal/inventory/types.go index e0f13f26..a3215133 100644 --- a/internal/inventory/types.go +++ b/internal/inventory/types.go @@ -48,14 +48,15 @@ type Snapshot struct { } type AgentConfig struct { - TotalComponents int64 - RetentionPeriodSeconds int64 - EnabledComponents []string - DisabledComponents []string - InventoryEnabled bool - InventoryIntervalSeconds int64 - AttestationEnabled bool - AttestationIntervalSeconds int64 + TotalComponents int64 + RetentionPeriodSeconds int64 + MetricScrapeIntervalSeconds int64 + EnabledComponents []string + DisabledComponents []string + InventoryEnabled bool + InventoryIntervalSeconds int64 + AttestationEnabled bool + AttestationIntervalSeconds int64 } type Resources struct { diff --git a/internal/server/server.go b/internal/server/server.go index 8525056a..adabeb98 100644 --- a/internal/server/server.go +++ b/internal/server/server.go @@ -175,11 +175,7 @@ func initializeMachineID(ctx context.Context, dbRW, dbRO *sql.DB) (string, error // getHealthCheckInterval determines the health check interval from config func getHealthCheckInterval(config *config.Config) time.Duration { - healthCheckInterval := time.Minute // default - if config.HealthExporter != nil && config.HealthExporter.HealthCheckInterval.Duration > 0 { - healthCheckInterval = config.HealthExporter.HealthCheckInterval.Duration - } - return healthCheckInterval + return config.HealthCheckInterval() } func getInventorySyncInterval(config *config.Config) time.Duration { @@ -474,14 +470,15 @@ func (s *Server) startInventoryLoop( return machineinfo.GetMachineInfo(nvmlInstance, machineinfo.WithDCGMGPUIndexes(dcgmGPUIndexes)) }), &inventory.AgentConfig{ - TotalComponents: int64(len(allComponents)), - RetentionPeriodSeconds: retentionPeriodSeconds, - EnabledComponents: enabledComponents, - DisabledComponents: disabledComponents, - InventoryEnabled: inventoryEnabled, - InventoryIntervalSeconds: inventoryIntervalSeconds, - AttestationEnabled: attestationEnabled, - AttestationIntervalSeconds: attestationIntervalSeconds, + TotalComponents: int64(len(allComponents)), + RetentionPeriodSeconds: retentionPeriodSeconds, + MetricScrapeIntervalSeconds: cfg.MetricScrapeIntervalSeconds(), + EnabledComponents: enabledComponents, + DisabledComponents: disabledComponents, + InventoryEnabled: inventoryEnabled, + InventoryIntervalSeconds: inventoryIntervalSeconds, + AttestationEnabled: attestationEnabled, + AttestationIntervalSeconds: attestationIntervalSeconds, }, ) sink := inventorysink.NewBackendSink(agentstate.NewSQLite()) diff --git a/internal/validation/outbound/validator.go b/internal/validation/outbound/validator.go index ebe92775..7c0ca808 100644 --- a/internal/validation/outbound/validator.go +++ b/internal/validation/outbound/validator.go @@ -94,6 +94,7 @@ func ValidateNodeUpsertRequest(req *backendclient.NodeUpsertRequest) []Issue { validateNonNegative(&issues, "numeric", "agentConfig.totalComponents", req.AgentConfig.TotalComponents) validateNonNegative(&issues, "numeric", "agentConfig.retentionPeriodSeconds", req.AgentConfig.RetentionPeriodSeconds) + validateNonNegative(&issues, "numeric", "agentConfig.metricScrapeIntervalSeconds", req.AgentConfig.MetricScrapeIntervalSeconds) validateNonNegative(&issues, "numeric", "agentConfig.inventoryIntervalSeconds", req.AgentConfig.InventoryIntervalSeconds) validateNonNegative(&issues, "numeric", "agentConfig.attestationIntervalSeconds", req.AgentConfig.AttestationIntervalSeconds) diff --git a/internal/validation/outbound/validator_test.go b/internal/validation/outbound/validator_test.go index f5ac6a73..9ef8a4c3 100644 --- a/internal/validation/outbound/validator_test.go +++ b/internal/validation/outbound/validator_test.go @@ -37,6 +37,9 @@ func TestValidateNodeUpsertRequest(t *testing.T) { MachineID: "machine-1", SystemUUID: "not-a-uuid", Uptime: &now, + AgentConfig: backendclient.AgentConfig{ + MetricScrapeIntervalSeconds: -1, + }, Resources: backendclient.NodeResources{ CPUInfo: backendclient.CPUInfo{LogicalCores: "-1"}, MemoryInfo: backendclient.MemoryInfo{ @@ -64,6 +67,12 @@ func TestValidateNodeUpsertRequest(t *testing.T) { Field: "hostname", Message: "field is required", }) + require.Contains(t, issues, Issue{ + Severity: SeverityWarning, + Category: "numeric", + Field: "agentConfig.metricScrapeIntervalSeconds", + Message: "value is negative", + }) require.Contains(t, issues, Issue{ Severity: SeverityCritical, Category: "numeric",