1
1
package connections
2
2
3
3
import (
4
+ "context"
5
+ "fmt"
4
6
"os"
5
7
"path/filepath"
6
8
"runtime"
9
+ "text/template"
7
10
11
+ logger "github.com/observeinc/observe-agent/internal/commands/util"
8
12
"github.com/spf13/viper"
13
+ "go.uber.org/zap"
9
14
)
10
15
16
+ var TempFilesFolder = "observe-agent"
17
+
11
18
type ConfigFieldHandler interface {
12
19
GenerateCollectorConfigFragment () interface {}
13
20
}
@@ -20,6 +27,10 @@ type CollectorConfigFragment struct {
20
27
type ConnectionType struct {
21
28
Name string
22
29
ConfigFields []CollectorConfigFragment
30
+ Type string
31
+
32
+ configFolderPath string
33
+ getConfig func () * viper.Viper
23
34
}
24
35
25
36
func GetConfigFolderPath () string {
@@ -39,23 +50,111 @@ func GetConfigFolderPath() string {
39
50
}
40
51
}
41
52
42
- func (c ConnectionType ) GetConfigFilePaths () []string {
43
- var rawConnConfig = viper .Sub (c .Name )
44
- configPaths := make ([]string , 0 )
45
- if rawConnConfig == nil || ! rawConnConfig .GetBool ("enabled" ) {
46
- return configPaths
53
+ func (c * ConnectionType ) GetTemplateFilepath (tplFilename string ) string {
54
+ return filepath .Join (c .configFolderPath , c .Name , tplFilename )
55
+ }
56
+
57
+ func (c * ConnectionType ) RenderConfigTemplate (ctx context.Context , tmpDir string , tplFilename string , confValues any ) (string , error ) {
58
+ tplPath := c .GetTemplateFilepath (tplFilename )
59
+ tmpl , err := template .New ("" ).Funcs (GetTemplateFuncMap ()).ParseFiles (tplPath )
60
+ if err != nil {
61
+ logger .FromCtx (ctx ).Error ("failed to parse config fragment template" , zap .String ("file" , tplPath ), zap .Error (err ))
62
+ return "" , err
47
63
}
64
+ f , err := os .CreateTemp (tmpDir , fmt .Sprintf ("*-%s" , tplFilename ))
65
+ if err != nil {
66
+ logger .FromCtx (ctx ).Error ("failed to create temporary config fragment file" , zap .String ("file" , tplPath ), zap .Error (err ))
67
+ return "" , err
68
+ }
69
+ err = tmpl .ExecuteTemplate (f , tplFilename , confValues )
70
+ if err != nil {
71
+ logger .FromCtx (ctx ).Error ("failed to execute config fragment template" , zap .String ("file" , tplPath ), zap .Error (err ))
72
+ return "" , err
73
+ }
74
+ return f .Name (), nil
75
+ }
76
+
77
+ func (c * ConnectionType ) ProcessConfigFields (ctx context.Context , tmpDir string , rawConnConfig * viper.Viper , confValues any ) ([]string , error ) {
78
+ paths := make ([]string , 0 )
48
79
for _ , field := range c .ConfigFields {
49
80
val := rawConnConfig .GetBool (field .configYAMLPath )
50
81
if val && field .colConfigFilePath != "" {
51
- configPath := filepath .Join (GetConfigFolderPath (), c .Name , field .colConfigFilePath )
52
- configPaths = append (configPaths , configPath )
82
+ configPath , err := c .RenderConfigTemplate (ctx , tmpDir , field .colConfigFilePath , confValues )
83
+ if err != nil {
84
+ return nil , err
85
+ }
86
+ paths = append (paths , configPath )
87
+ }
88
+ }
89
+ return paths , nil
90
+ }
91
+
92
+ func (c * ConnectionType ) GetConfigFilePaths (ctx context.Context , tmpDir string ) ([]string , error ) {
93
+ var rawConnConfig = c .getConfig ()
94
+ var configPaths []string
95
+ if rawConnConfig == nil || ! rawConnConfig .GetBool ("enabled" ) {
96
+ return configPaths , nil
97
+ }
98
+ switch c .Type {
99
+ case SelfMonitoringConnectionTypeName :
100
+ conf := & SelfMonitoringConfig {}
101
+ err := rawConnConfig .Unmarshal (conf )
102
+ if err != nil {
103
+ logger .FromCtx (ctx ).Error ("failed to unmarshal config" , zap .String ("connection" , c .Name ))
104
+ return nil , err
105
+ }
106
+ configPaths , err = c .ProcessConfigFields (ctx , tmpDir , rawConnConfig , conf )
107
+ if err != nil {
108
+ return nil , err
53
109
}
110
+ case HostMonitoringConnectionTypeName :
111
+ conf := & HostMonitoringConfig {}
112
+ err := rawConnConfig .Unmarshal (conf )
113
+ if err != nil {
114
+ logger .FromCtx (ctx ).Error ("failed to unmarshal config" , zap .String ("connection" , c .Name ))
115
+ return nil , err
116
+ }
117
+ configPaths , err = c .ProcessConfigFields (ctx , tmpDir , rawConnConfig , conf )
118
+ if err != nil {
119
+ return nil , err
120
+ }
121
+ default :
122
+ logger .FromCtx (ctx ).Error ("unknown connection type" , zap .String ("type" , c .Type ))
123
+ return nil , fmt .Errorf ("unknown connection type %s" , c .Type )
124
+ }
125
+ return configPaths , nil
126
+ }
127
+
128
+ type ConnectionTypeOption func (* ConnectionType )
129
+
130
+ func MakeConnectionType (Name string , ConfigFields []CollectorConfigFragment , Type string , opts ... ConnectionTypeOption ) * ConnectionType {
131
+ var c = & ConnectionType {Name : Name , ConfigFields : ConfigFields , Type : Type }
132
+ c .getConfig = func () * viper.Viper {
133
+ return viper .Sub (c .Name )
134
+ }
135
+ c .configFolderPath = GetConfigFolderPath ()
136
+
137
+ // Apply provided options
138
+ for _ , opt := range opts {
139
+ opt (c )
140
+ }
141
+
142
+ return c
143
+ }
144
+
145
+ func WithConfigFolderPath (configFolderPath string ) ConnectionTypeOption {
146
+ return func (c * ConnectionType ) {
147
+ c .configFolderPath = configFolderPath
148
+ }
149
+ }
150
+
151
+ func WithGetConfig (getConfig func () * viper.Viper ) ConnectionTypeOption {
152
+ return func (c * ConnectionType ) {
153
+ c .getConfig = getConfig
54
154
}
55
- return configPaths
56
155
}
57
156
58
157
var AllConnectionTypes = []* ConnectionType {
59
- & HostMonitoringConnectionType ,
60
- & SelfMonitoringConnectionType ,
158
+ HostMonitoringConnectionType ,
159
+ SelfMonitoringConnectionType ,
61
160
}
0 commit comments