Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
ad366fa
feat(procmgr): wire condition_config_any into process auto-start
jose-manuel-almaza Aug 14, 2026
1be8013
feat(procmgr): add Windows platform helpers for config gates (split P…
jose-manuel-almaza Aug 12, 2026
7fa9099
feat(procmgr): config gates for processes.d auto-start (split PR 2/4)
jose-manuel-almaza Aug 11, 2026
cab3925
fix(procmgr): sync config gate YAML and system_probe fixes from #53249
jose-manuel-almaza Aug 11, 2026
68248ee
fix(config): restore sketch v3beta shadow schema defaults
jose-manuel-almaza Aug 11, 2026
77dd1d3
fix(procmgr): expand env vars in condition_config_any paths
jose-manuel-almaza Aug 12, 2026
5f09b32
fix(procmgr): accept YAML 1.1 bool spellings in config gates
jose-manuel-almaza Aug 12, 2026
23fe8c1
test(procmgr): add config gate integration tests on config-gates PR
jose-manuel-almaza Aug 12, 2026
3653da7
chore(config): revert accidental BUILD.bazel comment changes
jose-manuel-almaza Aug 12, 2026
c37e26e
fix(procmgr): honor Linux discovery.enabled platform default in confi…
jose-manuel-almaza Aug 12, 2026
87f7761
fix(procmgr): read fleet_policies_dir from gated config file
jose-manuel-almaza Aug 12, 2026
33081af
fix(procmgr): match Go yaml.v2 plain vs quoted bool coercion in confi…
jose-manuel-almaza Aug 12, 2026
bc63e90
fix(procmgr): resolve PATHEXT executables case-insensitively on Windows
jose-manuel-almaza Aug 12, 2026
478fd15
fix(procmgr): fall back to inherit when Windows stdio file redirect f…
jose-manuel-almaza Aug 12, 2026
fe05fbd
fix(procmgr): discard orphaned restarts after process removal
jose-manuel-almaza Aug 13, 2026
5d0282a
fix(procmgr): finish may_auto_start rename in config gate test
jose-manuel-almaza Aug 13, 2026
0696322
fix(procmgr): preserve successful-run state across config reload
jose-manuel-almaza Aug 13, 2026
67c4161
chore(procmgr): trim redundant comments in spawn-profile PR
jose-manuel-almaza Aug 13, 2026
28ab29f
refactor(procmgr): simplify reload restart handling
jose-manuel-almaza Aug 13, 2026
5cd9278
Fix procmgr CI: rustfmt, clippy, and ddot e2e log expectation.
jose-manuel-almaza Aug 14, 2026
3133f49
fix(procmgr): keep list/describe process state after config-gates rebase
jose-manuel-almaza Aug 14, 2026
3675484
fix(procmgr): align manager reload path after stack rebase onto main
jose-manuel-almaza Aug 14, 2026
3b57713
fix(procmgr): restore reload helpers after stack rebase onto spawn-pr…
jose-manuel-almaza Aug 14, 2026
a0066b5
docs(procmgr): point config gate env bindings at schema source of truth
jose-manuel-almaza Aug 11, 2026
10e542e
fix(procmgr): resolve rebase fallout in process.rs and manager tests
jose-manuel-almaza Aug 14, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions pkg/config/schema/yaml/core_schema.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ properties:
Infrastructure mode
The infrastructure mode is used to determine the features that are available to the agent.
The possible values are: full, basic, end_user_device, cloud_cost_only, none.
Mirrored in pkg/procmgr/rust/src/config_gate/env_bindings.rs for procmgr config gates.
dd_url:
node_type: setting
type: string
Expand Down Expand Up @@ -7803,6 +7804,9 @@ properties:
node_type: setting
type: boolean
default: false
comment: |-
Non-default env bindings for keys used by procmgr config gates are mirrored in
pkg/procmgr/rust/src/config_gate/env_bindings.rs.
include_ephemeral_containers:
node_type: setting
type: boolean
Expand Down
1 change: 1 addition & 0 deletions pkg/config/schema/yaml/process_config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,7 @@ properties:
- DD_PROCESS_CONFIG_ENABLED
- DD_PROCESS_AGENT_ENABLED
comment: |-
Env bindings below are mirrored in pkg/procmgr/rust/src/config_gate/env_bindings.rs.
"process_config.enabled" is deprecated. We must still be able to detect if it is present, to know if we should use it
or container_collection.enabled and process_collection.enabled.

Expand Down
1 change: 1 addition & 0 deletions pkg/config/setup/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ dd_agent_go_test(
"config_init_test.go",
"config_secret_test.go",
"config_test.go",
"config_windows_test.go",
"privateactionrunner_test.go",
"process_test.go",
"system_probe_test.go",
Expand Down
28 changes: 25 additions & 3 deletions pkg/config/setup/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ func unsetProxyEnvForTest(t *testing.T) {
}
}

// testFleetPoliciesDir is a fixed path used in YAML round-trip tests so fleet_policies_dir
// is deterministic across platforms (env is read during InitConfig; FleetConfigOverride skips when set).
const testFleetPoliciesDir = `C:\testdata\fleet\policies`

func TestDefaults(t *testing.T) {
config := newTestConf(t)

Expand Down Expand Up @@ -1394,6 +1398,7 @@ process_config:
`)

func TestConfigAssignAtPath(t *testing.T) {
t.Setenv("DD_FLEET_POLICIES_DIR", testFleetPoliciesDir)

config := newTestConf(t)
config.SetInTest("use_proxy_for_cloud_metadata", true)
Expand All @@ -1420,6 +1425,7 @@ func TestConfigAssignAtPath(t *testing.T) {
- changed
https://url2.eu:
- third
fleet_policies_dir: C:\testdata\fleet\policies
process_config:
additional_endpoints:
https://url1.com:
Expand Down Expand Up @@ -1485,6 +1491,7 @@ secret_backend_arguments:
`)

func TestConfigAssignAtPathSimple(t *testing.T) {
t.Setenv("DD_FLEET_POLICIES_DIR", testFleetPoliciesDir)

config := newTestConf(t)
config.SetInTest("use_proxy_for_cloud_metadata", true)
Expand All @@ -1498,7 +1505,8 @@ func TestConfigAssignAtPathSimple(t *testing.T) {
err = configAssignAtPath(config, []string{"secret_backend_arguments", "0"}, "password1")
assert.NoError(t, err)

expectedYaml := `secret_backend_arguments:
expectedYaml := `fleet_policies_dir: C:\testdata\fleet\policies
secret_backend_arguments:
- password1
secret_backend_command: some command
use_proxy_for_cloud_metadata: true
Expand All @@ -1510,6 +1518,7 @@ use_proxy_for_cloud_metadata: true
}

func TestConfigMustMatchOrigin(t *testing.T) {
t.Setenv("DD_FLEET_POLICIES_DIR", testFleetPoliciesDir)

testMinimalConf := []byte(`apm_config:
apm_dd_url: ENC[some_url]
Expand All @@ -1525,13 +1534,20 @@ use_proxy_for_cloud_metadata: true

expectedYaml := `apm_config:
apm_dd_url: first_value
fleet_policies_dir: C:\testdata\fleet\policies
secret_backend_command: command
use_proxy_for_cloud_metadata: true
`
expectedDiffYaml := `apm_config:
apm_dd_url: second_value
secret_backend_command: command
use_proxy_for_cloud_metadata: true
`
expectedDiffConfigYaml := `apm_config:
apm_dd_url: second_value
fleet_policies_dir: C:\testdata\fleet\policies
secret_backend_command: command
use_proxy_for_cloud_metadata: true
`

config := newTestConf(t)
Expand Down Expand Up @@ -1573,7 +1589,7 @@ use_proxy_for_cloud_metadata: true
// now the original config was modified because of the origin match
yamlConf, err = yaml.Marshal(config.AllSettingsWithoutDefault())
assert.NoError(t, err)
assert.YAMLEq(t, expectedDiffYaml, string(yamlConf))
assert.YAMLEq(t, expectedDiffConfigYaml, string(yamlConf))
}

func TestConfigAssignAtPathForIntMapKeys(t *testing.T) {
Expand Down Expand Up @@ -1604,9 +1620,15 @@ additional_endpoints:
)
}

func TestServerlessConfigNumComponents(t *testing.T) {
// Enforce the number of config "components" reachable by the serverless agent
// to avoid accidentally adding entire components if it's not needed
require.Len(t, commonConfigComponents, 24)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is commonConfigComponents defined?

}

func TestServerlessConfigInit(t *testing.T) {
conf := newEmptyMockConf(t)
initCommonBase(conf)
initCommonConfigComponents(conf)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it defined anywhere?


// ensure some core configs are declared
assert.True(t, conf.IsKnown("api_key"))
Expand Down
42 changes: 37 additions & 5 deletions pkg/config/setup/config_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,27 +6,59 @@
package setup

import (
"path/filepath"

pkgconfigmodel "github.com/DataDog/datadog-agent/pkg/config/model"
"github.com/DataDog/datadog-agent/pkg/util/winutil"
)

// FleetConfigOverride sets the fleet_policies_dir config value to the value set in the registry.
// FleetConfigOverride sets fleet_policies_dir for every Windows agent binary that loads
// config through pkg/config/setup (registered in fixup_init; system-probe calls it directly).
//
// Resolution order (first non-empty wins): datadog.yaml / DD_FLEET_POLICIES_DIR, then the
// registry experiment path, then defaultStableFleetPoliciesDir. Mirrors dd-procmgr config
// gates in pkg/procmgr/rust/src/config_gate.rs.
//
// The stable ProgramData fallback is intentional global parity with procmgr-managed children
// (process-agent, PAR, DDOT): they no longer carry DD_FLEET_POLICIES_DIR in processes.d, so
// all Windows binaries must resolve the same managed policy directory without per-service env.
//
// This value tells the agent to load a config experiment from Fleet Automation.
// Standalone installs are unaffected: comp/core/config and system-probe call MergeFleetPolicy
// only after fleet_policies_dir is set, and MergeFleetPolicy no-ops when the policy YAML file
// is absent (pkg/config/nodetreemodel/config.go). On fleet-managed hosts between experiments
// (registry empty, stable managed datadog.yaml present), the stable layer now merges as
// SourceFleetPolicies — previously nothing merged in that window.
//
// Linux sets this option with an environment variable in the experiment's systemd unit file,
// so we need a different approach for Windows. After the viper migration is complete, we can
// consider replacing this override with a Windows Registry config source.
// Linux sets fleet_policies_dir via environment in experiment systemd units; after the viper
// migration we may replace this override with a Windows registry config source.
func FleetConfigOverride(config pkgconfigmodel.Config) {
// Prioritize the value set in the config file / env var
if config.IsConfigured("fleet_policies_dir") {
return
}

val := winutil.ReadFleetPoliciesDirFromRegistry()
if val == "" {
val = defaultStableFleetPoliciesDir()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So FleetConfigOverride changes every Windows Agent binary, not just procmgr. Is it expected?

}
if val == "" {
return
}

config.Set("fleet_policies_dir", val, pkgconfigmodel.SourceAgentRuntime)
}

// defaultStableFleetPoliciesDir returns the stable managed fleet policies directory under
// ProgramData. Matches pkg/fleet/installer/paths.FleetPoliciesDirForManagedProcess without
// importing fleet/installer (circular dependency with config/setup).
//
// Used as the global FleetConfigOverride fallback, not only for dd-procmgr: every Windows
// binary that merges fleet policy YAML must find the same stable directory when the registry
// experiment path is unset.
func defaultStableFleetPoliciesDir() string {
dataDir, err := winutil.GetProgramDataDirForProduct("Datadog Agent")
if err != nil || dataDir == "" {
return ""
}
return filepath.Join(dataDir, "Installer", "managed", "datadog-agent", "stable")
}
40 changes: 40 additions & 0 deletions pkg/config/setup/config_windows_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// Unless explicitly stated otherwise all files in this repository are licensed
// under the Apache License Version 2.0.
// This product includes software developed at Datadog (https://www.datadoghq.com/).
// Copyright 2016-present Datadog, Inc.

//go:build windows && test

package setup

import (
"path/filepath"
"strings"
"testing"

"github.com/stretchr/testify/assert"
)

const expectedStableFleetPoliciesRel = "datadog-agent/stable"

func TestFleetConfigOverride_FallsBackToStableFleetPoliciesDirWhenUnset(t *testing.T) {
t.Setenv("DD_FLEET_POLICIES_DIR", "")

config := newTestConf(t)
FleetConfigOverride(config)

dir := config.GetString("fleet_policies_dir")
assert.NotEmpty(t, dir)
normalized := filepath.ToSlash(filepath.Clean(dir))
assert.True(t, strings.HasSuffix(normalized, expectedStableFleetPoliciesRel), normalized)
}

func TestFleetConfigOverride_RespectsEnvOverride(t *testing.T) {
const customDir = `C:\custom\fleet\policies`
t.Setenv("DD_FLEET_POLICIES_DIR", customDir)

config := newTestConf(t)
FleetConfigOverride(config)

assert.Equal(t, customDir, config.GetString("fleet_policies_dir"))
}
2 changes: 2 additions & 0 deletions pkg/procmgr/rust/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ log.workspace = true
serde = { workspace = true, features = ["derive"] }
serde_json.workspace = true
serde_yaml.workspace = true
saphyr-parser = { workspace = true }
dd-agent-log.workspace = true
dd-procmgr-client.workspace = true
tokio = { workspace = true, features = ["macros", "rt-multi-thread", "signal", "process", "fs", "time", "sync"] }
Expand Down Expand Up @@ -68,6 +69,7 @@ nix = { workspace = true, features = ["signal", "process", "user"] }

[dev-dependencies]
tempfile.workspace = true
hyper-util = { workspace = true, features = ["tokio"] }

[[test]]
name = "e2e"
Expand Down
33 changes: 33 additions & 0 deletions pkg/procmgr/rust/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
// This product includes software developed at Datadog (https://www.datadoghq.com/).
// Copyright 2026-present Datadog, Inc.


use crate::config_gate::ConditionConfigFile;
use crate::platform;
use anyhow::{Context, Result};
use log::{debug, info, warn};
Expand Down Expand Up @@ -193,6 +195,8 @@ pub struct ProcessConfig {
#[serde(default = "default_true")]
pub auto_start: bool,
pub condition_path_exists: Option<String>,
#[serde(default)]
pub condition_config_any: Vec<ConditionConfigFile>,
pub stop_timeout: Option<u64>,
#[serde(default = "default_restart")]
pub restart: RestartPolicy,
Expand Down Expand Up @@ -228,6 +232,7 @@ impl Default for ProcessConfig {
stderr: "inherit".to_string(),
auto_start: true,
condition_path_exists: None,
condition_config_any: Vec::new(),
stop_timeout: None,
restart: RestartPolicy::Never,
restart_sec: None,
Expand Down Expand Up @@ -484,6 +489,34 @@ condition_path_exists: /usr/bin/sleep
assert!(result.is_err());
}

#[test]
fn test_process_agent_config_gate_parsing() {
let dir = tempfile::tempdir().unwrap();
let yaml = r#"
command: /bin/process-agent
auto_start: true
condition_config_any:
- path: /etc/datadog-agent/datadog.yaml
keys:
- process_config.enabled
- process_config.process_collection.enabled
- path: /etc/datadog-agent/system-probe.yaml
keys:
- network_config.enabled
"#;
fs::write(dir.path().join("proc.yaml"), yaml).unwrap();
let configs = load_configs(dir.path()).unwrap();
assert_eq!(configs.len(), 1);
assert_eq!(configs[0].config.condition_config_any.len(), 2);
assert_eq!(
configs[0].config.condition_config_any[0].keys,
vec![
"process_config.enabled".to_string(),
"process_config.process_collection.enabled".to_string(),
]
);
}

#[test]
fn test_ddot_example_config() {
let dir = tempfile::tempdir().unwrap();
Expand Down
Loading
Loading