4
4
package supervisor
5
5
6
6
import (
7
+ "bufio"
7
8
"bytes"
8
9
"context"
9
10
"crypto/tls"
@@ -16,6 +17,7 @@ import (
16
17
"os"
17
18
"path/filepath"
18
19
"sort"
20
+ "strings"
19
21
"sync"
20
22
"sync/atomic"
21
23
"text/template"
73
75
)
74
76
75
77
const (
76
- persistentStateFileName = "persistent_state.yaml"
77
- agentConfigFileName = "effective.yaml"
78
+ persistentStateFileName = "persistent_state.yaml"
79
+ agentConfigFileName = "effective.yaml"
80
+ AllowNoPipelinesFeatureGate = "service.AllowNoPipelines"
78
81
)
79
82
80
83
const maxBufferedCustomMessages = 10
@@ -182,6 +185,8 @@ type Supervisor struct {
182
185
opampServerPort int
183
186
184
187
telemetrySettings telemetrySettings
188
+
189
+ featureGates map [string ]struct {}
185
190
}
186
191
187
192
func NewSupervisor (logger * zap.Logger , cfg config.Supervisor ) (* Supervisor , error ) {
@@ -196,6 +201,7 @@ func NewSupervisor(logger *zap.Logger, cfg config.Supervisor) (*Supervisor, erro
196
201
doneChan : make (chan struct {}),
197
202
customMessageToServer : make (chan * protobufs.CustomMessage , maxBufferedCustomMessages ),
198
203
agentConn : & atomic.Value {},
204
+ featureGates : map [string ]struct {}{},
199
205
}
200
206
if err := s .createTemplates (); err != nil {
201
207
return nil , err
@@ -312,6 +318,10 @@ func (s *Supervisor) Start() error {
312
318
return err
313
319
}
314
320
321
+ if err = s .getFeatureGates (); err != nil {
322
+ return fmt .Errorf ("could not get feature gates from the Collector: %w" , err )
323
+ }
324
+
315
325
if err = s .getBootstrapInfo (); err != nil {
316
326
return fmt .Errorf ("could not get bootstrap info from the Collector: %w" , err )
317
327
}
@@ -365,6 +375,41 @@ func (s *Supervisor) Start() error {
365
375
return nil
366
376
}
367
377
378
+ func (s * Supervisor ) getFeatureGates () error {
379
+ cmd , err := commander .NewCommander (
380
+ s .telemetrySettings .Logger ,
381
+ s .config .Storage .Directory ,
382
+ s .config .Agent ,
383
+ "featuregate" ,
384
+ )
385
+ if err != nil {
386
+ return err
387
+ }
388
+
389
+ stdout , _ , err := cmd .StartOneShot ()
390
+ if err != nil {
391
+ return err
392
+ }
393
+ scanner := bufio .NewScanner (bytes .NewBuffer (stdout ))
394
+
395
+ // First line only contains headers, discard it.
396
+ _ = scanner .Scan ()
397
+ for scanner .Scan () {
398
+ line := scanner .Text ()
399
+ i := strings .Index (line , " " )
400
+ flag := line [0 :i ]
401
+
402
+ if flag == AllowNoPipelinesFeatureGate {
403
+ s .featureGates [AllowNoPipelinesFeatureGate ] = struct {}{}
404
+ }
405
+ }
406
+ if err := scanner .Err (); err != nil {
407
+ fmt .Fprintln (os .Stderr , "reading standard input:" , err )
408
+ }
409
+
410
+ return nil
411
+ }
412
+
368
413
func (s * Supervisor ) createTemplates () error {
369
414
var err error
370
415
@@ -498,11 +543,18 @@ func (s *Supervisor) getBootstrapInfo() (err error) {
498
543
}
499
544
}()
500
545
546
+ flags := []string {
547
+ "--config" , s .agentConfigFilePath (),
548
+ }
549
+ featuregateFlag := s .getFeatureGateFlag ()
550
+ if len (featuregateFlag ) > 0 {
551
+ flags = append (flags , featuregateFlag ... )
552
+ }
501
553
cmd , err := commander .NewCommander (
502
554
s .telemetrySettings .Logger ,
503
555
s .config .Storage .Directory ,
504
556
s .config .Agent ,
505
- "--config" , s . agentConfigFilePath () ,
557
+ flags ... ,
506
558
)
507
559
if err != nil {
508
560
span .SetStatus (codes .Error , fmt .Sprintf ("Could not start Agent: %v" , err ))
@@ -902,12 +954,12 @@ func (s *Supervisor) onOpampConnectionSettings(_ context.Context, settings *prot
902
954
903
955
func (s * Supervisor ) composeNoopPipeline () ([]byte , error ) {
904
956
var cfg bytes.Buffer
905
- err := s . noopPipelineTemplate . Execute ( & cfg , map [ string ] any {
906
- "InstanceUid" : s . persistentState . InstanceID . String (),
907
- "SupervisorPort" : s .opampServerPort ,
908
- })
909
- if err != nil {
910
- return nil , err
957
+
958
+ if ! s . isFeatureGateSupported ( AllowNoPipelinesFeatureGate ) {
959
+ err := s .noopPipelineTemplate . Execute ( & cfg , map [ string ] any {})
960
+ if err != nil {
961
+ return nil , err
962
+ }
911
963
}
912
964
913
965
return cfg .Bytes (), nil
@@ -1664,6 +1716,24 @@ func (s *Supervisor) getSupervisorOpAMPServerPort() (int, error) {
1664
1716
return s .findRandomPort ()
1665
1717
}
1666
1718
1719
+ func (s * Supervisor ) getFeatureGateFlag () []string {
1720
+ flags := []string {}
1721
+ for k , _ := range s .featureGates {
1722
+ flags = append (flags , k )
1723
+ }
1724
+
1725
+ if len (flags ) == 0 {
1726
+ return []string {}
1727
+ }
1728
+
1729
+ return []string {"--feature-gates" , strings .Join (flags , "," )}
1730
+ }
1731
+
1732
+ func (s * Supervisor ) isFeatureGateSupported (gate string ) bool {
1733
+ _ , ok := s .featureGates [gate ]
1734
+ return ok
1735
+ }
1736
+
1667
1737
func (s * Supervisor ) findRandomPort () (int , error ) {
1668
1738
l , err := net .Listen ("tcp" , "localhost:0" )
1669
1739
if err != nil {
0 commit comments