diff --git a/comp/core/workloadmeta/collectors/catalog-core/options_nosbom.go b/comp/core/workloadmeta/collectors/catalog-core/options_nosbom.go index 371cf26db44f..27b90421954c 100644 --- a/comp/core/workloadmeta/collectors/catalog-core/options_nosbom.go +++ b/comp/core/workloadmeta/collectors/catalog-core/options_nosbom.go @@ -23,6 +23,7 @@ import ( "github.com/DataDog/datadog-agent/comp/core/workloadmeta/collectors/internal/nvml" "github.com/DataDog/datadog-agent/comp/core/workloadmeta/collectors/internal/podman" "github.com/DataDog/datadog-agent/comp/core/workloadmeta/collectors/internal/process" + remoteprocesscollector "github.com/DataDog/datadog-agent/comp/core/workloadmeta/collectors/internal/remote/processcollector" remotesbomcollector "github.com/DataDog/datadog-agent/comp/core/workloadmeta/collectors/internal/remote/sbomcollector" ) @@ -37,6 +38,7 @@ func getCollectorOptions() []fx.Option { kubelet.GetFxOptions(), kubemetadata.GetFxOptions(), podman.GetFxOptions(), + remoteprocesscollector.GetFxOptions(), remotesbomcollector.GetFxOptions(), nvml.GetFxOptions(), process.GetFxOptions(), diff --git a/test/new-e2e/tests/process/config/language_detection.yaml b/test/new-e2e/tests/process/config/language_detection.yaml new file mode 100644 index 000000000000..5be68a1e812f --- /dev/null +++ b/test/new-e2e/tests/process/config/language_detection.yaml @@ -0,0 +1,7 @@ +process_config: + process_collection: + enabled: true + intervals: + process: 1 +language_detection: + enabled: true diff --git a/test/new-e2e/tests/process/testing.go b/test/new-e2e/tests/process/testing.go index 6c5b7f265072..2a3357f6ee7c 100644 --- a/test/new-e2e/tests/process/testing.go +++ b/test/new-e2e/tests/process/testing.go @@ -42,6 +42,9 @@ var coreAgentRefreshStr string //go:embed config/process_agent_refresh_win.yaml var processAgentWinRefreshStr string +//go:embed config/language_detection.yaml +var languageDetectionConfigStr string + // AgentStatus is a subset of the agent's status response for asserting the process-agent runtime type AgentStatus struct { ProcessAgentStatus struct { diff --git a/test/new-e2e/tests/process/windows_test.go b/test/new-e2e/tests/process/windows_test.go index 85eefdef62d4..afc3973f01ef 100644 --- a/test/new-e2e/tests/process/windows_test.go +++ b/test/new-e2e/tests/process/windows_test.go @@ -308,6 +308,65 @@ func (s *windowsTestSuite) TestManualUnprotectedProcessCheckWithIO() { }, 1*time.Minute, 5*time.Second) } +// TODO(CXP-3410): Unskip once gRPC stream cycling after MSI reinstall is fixed. +// See https://datadoghq.atlassian.net/browse/CXP-3410 +func (s *windowsTestSuite) TestLanguageDetectionWindows() { + s.T().Skip("Skipped: gRPC stream cycling after MSI reinstall prevents language data delivery (CXP-3410)") + t := s.T() + + // Enable language detection on the agent + s.UpdateEnv(awshost.Provisioner( + awshost.WithRunOptions( + ec2.WithEC2InstanceOptions(ec2.WithOS(os.WindowsServerDefault)), + ec2.WithAgentOptions(agentparams.WithAgentConfig(languageDetectionConfigStr)), + ), + )) + + // Start Python in a persistent SSH session so it survives across commands + s.Env().RemoteHost.MustExecute(`Set-Content -Path C:\sleep.py -Value "import time; time.sleep(600)"`) + pythonPath := `"C:\Program Files\Datadog\Datadog Agent\embedded3\python.exe" C:\sleep.py` + session, stdin, _, err := s.Env().RemoteHost.Start(pythonPath) + require.NoError(t, err, "Failed to start python") + t.Cleanup(func() { + _ = session.Close() + _ = stdin.Close() + }) + + // Check that any process entity has Language.Name == "python" in the core agent's workload-list. + type workloadProcess struct { + Kind string `json:"Kind"` + ID string `json:"ID"` + Language *struct { + Name string `json:"Name"` + } `json:"Language"` + } + type workloadResponse struct { + Entities map[string][]workloadProcess `json:"Entities"` + } + + var lastOutput string + assert.EventuallyWithT(t, func(c *assert.CollectT) { + out, err := s.Env().RemoteHost.Execute(`& "C:\Program Files\Datadog\Datadog Agent\bin\agent.exe" workload-list --json`) + if !assert.NoError(c, err, "workload-list command failed") { + return + } + lastOutput = out + var resp workloadResponse + if !assert.NoError(c, json.Unmarshal([]byte(lastOutput), &resp), "failed to parse workload-list JSON") { + return + } + for _, p := range resp.Entities["process"] { + if p.Language != nil && p.Language.Name == "python" { + return + } + } + assert.Fail(c, "no process with language=python found in workload-list") + }, 2*time.Minute, 5*time.Second) + if t.Failed() { + t.Logf("Last workload-list --json output:\n%s", lastOutput) + } +} + // Runs Diskspd in another ssh session // https://github.com/Microsoft/diskspd/wiki/Command-line-and-parameters // diskspd is an unprotected process, so we can capture the command line