Skip to content

Commit b2a8245

Browse files
committed
discovery: add system-probe-lite support
1 parent ae90bec commit b2a8245

2 files changed

Lines changed: 240 additions & 13 deletions

File tree

internal/controller/datadogagent/feature/servicediscovery/feature.go

Lines changed: 54 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
package servicediscovery
77

88
import (
9+
"fmt"
10+
911
corev1 "k8s.io/api/core/v1"
1012
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1113

@@ -31,6 +33,7 @@ func buildFeature(*feature.Options) feature.Feature {
3133

3234
type serviceDiscoveryFeature struct {
3335
networkStatsEnabled bool
36+
useSystemProbeLite bool
3437
}
3538

3639
// ID returns the ID of the Feature
@@ -40,21 +43,51 @@ func (f *serviceDiscoveryFeature) ID() feature.IDType {
4043

4144
// Configure is used to configure the feature from a v2alpha1.DatadogAgent instance.
4245
func (f *serviceDiscoveryFeature) Configure(_ metav1.Object, ddaSpec *v2alpha1.DatadogAgentSpec, _ *v2alpha1.RemoteConfigConfiguration) (reqComp feature.RequiredComponents) {
43-
if ddaSpec.Features != nil && ddaSpec.Features.ServiceDiscovery != nil && apiutils.BoolValue(ddaSpec.Features.ServiceDiscovery.Enabled) {
44-
reqComp.Agent = feature.RequiredComponent{
45-
IsRequired: apiutils.NewBoolPointer(true),
46-
Containers: []apicommon.AgentContainerName{apicommon.CoreAgentContainerName, apicommon.SystemProbeContainerName},
47-
}
46+
if ddaSpec.Features == nil || ddaSpec.Features.ServiceDiscovery == nil {
47+
return reqComp
48+
}
4849

49-
f.networkStatsEnabled = true
50-
if ddaSpec.Features.ServiceDiscovery.NetworkStats != nil {
51-
f.networkStatsEnabled = apiutils.BoolValue(ddaSpec.Features.ServiceDiscovery.NetworkStats.Enabled)
52-
}
50+
sd := ddaSpec.Features.ServiceDiscovery
51+
if !apiutils.BoolValue(sd.Enabled) {
52+
return reqComp
5353
}
5454

55+
reqComp.Agent = feature.RequiredComponent{
56+
IsRequired: apiutils.NewBoolPointer(true),
57+
Containers: []apicommon.AgentContainerName{apicommon.CoreAgentContainerName, apicommon.SystemProbeContainerName},
58+
}
59+
60+
f.networkStatsEnabled = true
61+
if sd.NetworkStats != nil {
62+
f.networkStatsEnabled = apiutils.BoolValue(sd.NetworkStats.Enabled)
63+
}
64+
65+
f.useSystemProbeLite = !hasOtherSystemProbeFeatures(ddaSpec.Features)
66+
5567
return reqComp
5668
}
5769

70+
func systemProbeLiteCommand(socketPath string) string {
71+
return fmt.Sprintf("if command -v system-probe-lite > /dev/null 2>&1; then exec system-probe-lite run --socket %s --log-level ${DD_LOG_LEVEL:-info}; else exec system-probe --config=/etc/datadog-agent/system-probe.yaml; fi",
72+
socketPath)
73+
}
74+
75+
// hasOtherSystemProbeFeatures returns true if any feature besides service discovery
76+
// requires the full system-probe binary. When true, system-probe-lite cannot be used.
77+
func hasOtherSystemProbeFeatures(features *v2alpha1.DatadogFeatures) bool {
78+
if features == nil {
79+
return false
80+
}
81+
return (features.NPM != nil && apiutils.BoolValue(features.NPM.Enabled)) ||
82+
(features.CWS != nil && apiutils.BoolValue(features.CWS.Enabled)) ||
83+
(features.CSPM != nil && apiutils.BoolValue(features.CSPM.Enabled) && apiutils.BoolValue(features.CSPM.RunInSystemProbe)) ||
84+
(features.USM != nil && apiutils.BoolValue(features.USM.Enabled)) ||
85+
(features.OOMKill != nil && apiutils.BoolValue(features.OOMKill.Enabled)) ||
86+
(features.TCPQueueLength != nil && apiutils.BoolValue(features.TCPQueueLength.Enabled)) ||
87+
(features.EBPFCheck != nil && apiutils.BoolValue(features.EBPFCheck.Enabled)) ||
88+
(features.GPU != nil && apiutils.BoolValue(features.GPU.Enabled) && apiutils.BoolValue(features.GPU.PrivilegedMode))
89+
}
90+
5891
// ManageDependencies allows a feature to manage its dependencies.
5992
// Feature's dependencies should be added in the store.
6093
func (f *serviceDiscoveryFeature) ManageDependencies(managers feature.ResourceManagers, provider string) error {
@@ -136,6 +169,18 @@ func (f *serviceDiscoveryFeature) ManageNodeAgent(managers feature.PodTemplateMa
136169
managers.EnvVar().AddEnvVarToContainer(apicommon.CoreAgentContainerName, socketEnvVar)
137170
managers.EnvVar().AddEnvVarToContainer(apicommon.SystemProbeContainerName, socketEnvVar)
138171

172+
// Direct PodTemplateSpec mutation: no managers API for command overrides.
173+
if f.useSystemProbeLite {
174+
for i := range managers.PodTemplateSpec().Spec.Containers {
175+
c := &managers.PodTemplateSpec().Spec.Containers[i]
176+
if c.Name == string(apicommon.SystemProbeContainerName) {
177+
c.Command = []string{"/bin/sh", "-c"}
178+
c.Args = []string{systemProbeLiteCommand(common.DefaultSystemProbeSocketPath)}
179+
break
180+
}
181+
}
182+
}
183+
139184
return nil
140185
}
141186

internal/controller/datadogagent/feature/servicediscovery/feature_test.go

Lines changed: 186 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,32 @@ func Test_serviceDiscoveryFeature_Configure(t *testing.T) {
4444
ddaServiceDiscoveryEnabledWithNetStats.Spec.Features.ServiceDiscovery.NetworkStats.Enabled = apiutils.NewBoolPointer(true)
4545
}
4646

47+
ddaWithNPM := v2alpha1.DatadogAgent{
48+
Spec: v2alpha1.DatadogAgentSpec{
49+
Features: &v2alpha1.DatadogFeatures{
50+
ServiceDiscovery: &v2alpha1.ServiceDiscoveryFeatureConfig{
51+
Enabled: apiutils.NewBoolPointer(true),
52+
},
53+
NPM: &v2alpha1.NPMFeatureConfig{
54+
Enabled: apiutils.NewBoolPointer(true),
55+
},
56+
},
57+
},
58+
}
59+
60+
ddaWithCWS := v2alpha1.DatadogAgent{
61+
Spec: v2alpha1.DatadogAgentSpec{
62+
Features: &v2alpha1.DatadogFeatures{
63+
ServiceDiscovery: &v2alpha1.ServiceDiscoveryFeatureConfig{
64+
Enabled: apiutils.NewBoolPointer(true),
65+
},
66+
CWS: &v2alpha1.CWSFeatureConfig{
67+
Enabled: apiutils.NewBoolPointer(true),
68+
},
69+
},
70+
},
71+
}
72+
4773
tests := test.FeatureTestSuite{
4874
{
4975
Name: "service discovery not enabled",
@@ -54,25 +80,168 @@ func Test_serviceDiscoveryFeature_Configure(t *testing.T) {
5480
Name: "service discovery enabled - no network stats",
5581
DDA: ddaServiceDiscoveryEnabledNoNetStats,
5682
WantConfigure: true,
57-
Agent: test.NewDefaultComponentTest().WithWantFunc(getWantFunc(noNetStats)),
83+
Agent: test.NewDefaultComponentTest().
84+
WithCreateFunc(createFuncWithSystemProbeContainer()).
85+
WithWantFunc(getWantFunc(noNetStats, true)),
5886
},
5987
{
6088
Name: "service discovery enabled - with network stats",
6189
DDA: ddaServiceDiscoveryEnabledWithNetStats,
6290
WantConfigure: true,
63-
Agent: test.NewDefaultComponentTest().WithWantFunc(getWantFunc(withNetStats)),
91+
Agent: test.NewDefaultComponentTest().
92+
WithCreateFunc(createFuncWithSystemProbeContainer()).
93+
WithWantFunc(getWantFunc(withNetStats, true)),
94+
},
95+
{
96+
Name: "system-probe-lite not used when NPM also enabled",
97+
DDA: &ddaWithNPM,
98+
WantConfigure: true,
99+
Agent: test.NewDefaultComponentTest().
100+
WithCreateFunc(createFuncWithSystemProbeContainer()).
101+
WithWantFunc(getWantFunc(withNetStats, false)),
102+
},
103+
{
104+
Name: "system-probe-lite not used when CWS also enabled",
105+
DDA: &ddaWithCWS,
106+
WantConfigure: true,
107+
Agent: test.NewDefaultComponentTest().
108+
WithCreateFunc(createFuncWithSystemProbeContainer()).
109+
WithWantFunc(getWantFunc(withNetStats, false)),
64110
},
65111
}
66112

67113
tests.Run(t, buildFeature)
68114
}
69115

116+
func Test_hasOtherSystemProbeFeatures(t *testing.T) {
117+
tests := []struct {
118+
name string
119+
features *v2alpha1.DatadogFeatures
120+
want bool
121+
}{
122+
{
123+
name: "nil features",
124+
features: nil,
125+
want: false,
126+
},
127+
{
128+
name: "no other features",
129+
features: &v2alpha1.DatadogFeatures{},
130+
want: false,
131+
},
132+
{
133+
name: "NPM enabled",
134+
features: &v2alpha1.DatadogFeatures{
135+
NPM: &v2alpha1.NPMFeatureConfig{Enabled: apiutils.NewBoolPointer(true)},
136+
},
137+
want: true,
138+
},
139+
{
140+
name: "CWS enabled",
141+
features: &v2alpha1.DatadogFeatures{
142+
CWS: &v2alpha1.CWSFeatureConfig{Enabled: apiutils.NewBoolPointer(true)},
143+
},
144+
want: true,
145+
},
146+
{
147+
name: "USM enabled",
148+
features: &v2alpha1.DatadogFeatures{
149+
USM: &v2alpha1.USMFeatureConfig{Enabled: apiutils.NewBoolPointer(true)},
150+
},
151+
want: true,
152+
},
153+
{
154+
name: "OOMKill enabled",
155+
features: &v2alpha1.DatadogFeatures{
156+
OOMKill: &v2alpha1.OOMKillFeatureConfig{Enabled: apiutils.NewBoolPointer(true)},
157+
},
158+
want: true,
159+
},
160+
{
161+
name: "TCPQueueLength enabled",
162+
features: &v2alpha1.DatadogFeatures{
163+
TCPQueueLength: &v2alpha1.TCPQueueLengthFeatureConfig{Enabled: apiutils.NewBoolPointer(true)},
164+
},
165+
want: true,
166+
},
167+
{
168+
name: "EBPFCheck enabled",
169+
features: &v2alpha1.DatadogFeatures{
170+
EBPFCheck: &v2alpha1.EBPFCheckFeatureConfig{Enabled: apiutils.NewBoolPointer(true)},
171+
},
172+
want: true,
173+
},
174+
{
175+
name: "CSPM enabled with RunInSystemProbe",
176+
features: &v2alpha1.DatadogFeatures{
177+
CSPM: &v2alpha1.CSPMFeatureConfig{
178+
Enabled: apiutils.NewBoolPointer(true),
179+
RunInSystemProbe: apiutils.NewBoolPointer(true),
180+
},
181+
},
182+
want: true,
183+
},
184+
{
185+
name: "CSPM enabled without RunInSystemProbe",
186+
features: &v2alpha1.DatadogFeatures{
187+
CSPM: &v2alpha1.CSPMFeatureConfig{
188+
Enabled: apiutils.NewBoolPointer(true),
189+
},
190+
},
191+
want: false,
192+
},
193+
{
194+
name: "GPU enabled with PrivilegedMode",
195+
features: &v2alpha1.DatadogFeatures{
196+
GPU: &v2alpha1.GPUFeatureConfig{
197+
Enabled: apiutils.NewBoolPointer(true),
198+
PrivilegedMode: apiutils.NewBoolPointer(true),
199+
},
200+
},
201+
want: true,
202+
},
203+
{
204+
name: "GPU enabled without PrivilegedMode",
205+
features: &v2alpha1.DatadogFeatures{
206+
GPU: &v2alpha1.GPUFeatureConfig{
207+
Enabled: apiutils.NewBoolPointer(true),
208+
},
209+
},
210+
want: false,
211+
},
212+
}
213+
214+
for _, tt := range tests {
215+
t.Run(tt.name, func(t *testing.T) {
216+
assert.Equal(t, tt.want, hasOtherSystemProbeFeatures(tt.features))
217+
})
218+
}
219+
}
220+
70221
const (
71222
noNetStats = false
72223
withNetStats = true
73224
)
74225

75-
func getWantFunc(withNetStats bool) func(t testing.TB, mgrInterface feature.PodTemplateManagers) {
226+
func createFuncWithSystemProbeContainer() func(testing.TB) (feature.PodTemplateManagers, string) {
227+
return func(t testing.TB) (feature.PodTemplateManagers, string) {
228+
newPTS := corev1.PodTemplateSpec{
229+
Spec: corev1.PodSpec{
230+
Containers: []corev1.Container{
231+
{
232+
Name: string(apicommon.CoreAgentContainerName),
233+
},
234+
{
235+
Name: string(apicommon.SystemProbeContainerName),
236+
},
237+
},
238+
},
239+
}
240+
return fake.NewPodTemplateManagers(t, newPTS), ""
241+
}
242+
}
243+
244+
func getWantFunc(withNetStats bool, useSPL bool) func(t testing.TB, mgrInterface feature.PodTemplateManagers) {
76245
return func(t testing.TB, mgrInterface feature.PodTemplateManagers) {
77246
mgr := mgrInterface.(*fake.PodTemplateManagers)
78247

@@ -200,7 +369,6 @@ func getWantFunc(withNetStats bool) func(t testing.TB, mgrInterface feature.PodT
200369
},
201370
}
202371

203-
// check env vars
204372
wantSPEnvVars := []*corev1.EnvVar{
205373
{
206374
Name: DDServiceDiscoveryEnabled,
@@ -221,6 +389,20 @@ func getWantFunc(withNetStats bool) func(t testing.TB, mgrInterface feature.PodT
221389

222390
systemProbeEnvVars := mgr.EnvVarMgr.EnvVarsByC[apicommon.SystemProbeContainerName]
223391
assert.True(t, apiutils.IsEqualStruct(systemProbeEnvVars, wantSPEnvVars), "System Probe envvars \ndiff = %s", cmp.Diff(systemProbeEnvVars, wantSPEnvVars))
392+
393+
// check system-probe container command override
394+
for _, c := range mgr.PodTemplateSpec().Spec.Containers {
395+
if c.Name == string(apicommon.SystemProbeContainerName) {
396+
if useSPL {
397+
assert.Equal(t, []string{"/bin/sh", "-c"}, c.Command, "System Probe command should be overridden for system-probe-lite")
398+
assert.Equal(t, []string{systemProbeLiteCommand(common.DefaultSystemProbeSocketPath)}, c.Args, "System Probe args mismatch")
399+
} else {
400+
assert.Empty(t, c.Command, "System Probe command should not be overridden")
401+
assert.Empty(t, c.Args, "System Probe args should not be overridden")
402+
}
403+
break
404+
}
405+
}
224406
}
225407
}
226408

0 commit comments

Comments
 (0)