Skip to content

Commit 6650dea

Browse files
committed
Add env var SPLUNK_CONFIG_YAML for storing configuration YAML
1 parent 0ec2599 commit 6650dea

File tree

6 files changed

+341
-88
lines changed

6 files changed

+341
-88
lines changed

cmd/otelcol/main.go

Lines changed: 103 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
package main
1919

2020
import (
21+
"bytes"
2122
"fmt"
2223
"log"
2324
"os"
@@ -26,6 +27,7 @@ import (
2627

2728
"go.opentelemetry.io/collector/component"
2829
"go.opentelemetry.io/collector/service"
30+
"go.opentelemetry.io/collector/service/parserprovider"
2931
"go.uber.org/zap"
3032

3133
"github.com/signalfx/splunk-otel-collector/internal/components"
@@ -37,6 +39,7 @@ import (
3739
const (
3840
ballastEnvVarName = "SPLUNK_BALLAST_SIZE_MIB"
3941
configEnvVarName = "SPLUNK_CONFIG"
42+
configYamlEnvVarName = "SPLUNK_CONFIG_YAML"
4043
configServerEnabledEnvVar = "SPLUNK_DEBUG_CONFIG_SERVER"
4144
memLimitMiBEnvVarName = "SPLUNK_MEMORY_LIMIT_MIB"
4245
memTotalEnvVarName = "SPLUNK_MEMORY_TOTAL_MIB"
@@ -57,8 +60,7 @@ func main() {
5760
// TODO: Use same format as the collector
5861
log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile)
5962

60-
args := os.Args[1:]
61-
if !contains(args, "-h") && !contains(args, "--help") {
63+
if !contains(os.Args[1:], "-h") && !contains(os.Args[1:], "--help") {
6264
checkRuntimeParams()
6365
}
6466

@@ -77,6 +79,7 @@ func main() {
7779
}
7880

7981
parserProvider := configprovider.NewConfigSourceParserProvider(
82+
newBaseParserProvider(),
8083
zap.NewNop(), // The service logger is not available yet, setting it to NoP.
8184
info,
8285
configsources.Get()...,
@@ -109,44 +112,29 @@ func contains(arr []string, str string) bool {
109112

110113
// Get the value of a key in an array
111114
// Support key/value with and with an equal sign
112-
func getKeyValue(args []string, argName string) string {
113-
val := ""
114-
for i, arg := range args {
115+
func getKeyValue(args []string, arg string) (exists bool, value string) {
116+
argEq := arg + "="
117+
for i := range args {
115118
switch {
116-
case strings.HasPrefix(arg, argName+"="):
117-
s := strings.Split(arg, "=")
118-
val = s[1]
119-
case arg == argName:
120-
i++
121-
val = args[i]
119+
case strings.HasPrefix(args[i], argEq):
120+
return true, strings.SplitN(args[i], "=", 2)[1]
121+
case args[i] == arg:
122+
exists = true
123+
if i < (len(args) - 1) {
124+
value = args[i+1]
125+
}
126+
return
122127
}
123128
}
124-
return val
129+
return
125130
}
126131

127132
// Check runtime parameters
128133
// Runtime parameters take priority over environment variables
129134
// Config and ballast flags are checked
130135
// Config and all memory env vars are checked
131136
func checkRuntimeParams() {
132-
args := os.Args[1:]
133-
config := ""
134-
135-
// Check if config flag was passed and its value differs from config env var.
136-
// If so, log that it will be used instead of env var value and set env var with that value.
137-
// This allows users to set `--config` and have it take priority when running from most contexts.
138-
cliConfig := getKeyValue(args, "--config")
139-
if cliConfig != "" {
140-
config = os.Getenv(configEnvVarName)
141-
if config != "" && config != cliConfig {
142-
log.Printf(
143-
"Both %v and '--config' were specified. Overriding %q environment variable value with %q for this session",
144-
configEnvVarName, config, cliConfig,
145-
)
146-
}
147-
os.Setenv(configEnvVarName, cliConfig)
148-
}
149-
setConfig()
137+
checkConfig()
150138

151139
// Set default total memory
152140
memTotalSizeMiB := defaultMemoryTotalMiB
@@ -169,66 +157,103 @@ func checkRuntimeParams() {
169157
// Check if memory ballast flag was passed
170158
// If so, ensure memory ballast env var is not set
171159
// Then set memory ballast and limit properly
172-
ballastSize := getKeyValue(args, "--mem-ballast-size-mib")
160+
_, ballastSize := getKeyValue(os.Args[1:], "--mem-ballast-size-mib")
173161
if ballastSize != "" {
174-
config = os.Getenv(ballastEnvVarName)
175-
if config != "" {
176-
log.Fatalf("Both %v and '--config' were specified, but only one is allowed", ballastEnvVarName)
162+
if os.Getenv(ballastEnvVarName) != "" {
163+
log.Fatalf("Both %v and '--mem-ballast-size-mib' were specified, but only one is allowed", ballastEnvVarName)
177164
}
178165
os.Setenv(ballastEnvVarName, ballastSize)
179166
}
180167
setMemoryBallast(memTotalSizeMiB)
181168
setMemoryLimit(memTotalSizeMiB)
182169
}
183170

184-
// Validate and set the configuration
185-
func setConfig() {
186-
// Check if the config is specified via the env var.
187-
config := os.Getenv(configEnvVarName)
188-
// If not attempt to use a default config; supports Docker and local
189-
if config == "" {
190-
_, err := os.Stat(defaultDockerSAPMConfig)
191-
if err == nil {
192-
config = defaultDockerSAPMConfig
171+
// Sets flag '--config' to specified env var SPLUNK_CONFIG, if the flag not specified.
172+
// Logs a message and returns if env var SPLUNK_CONFIG_YAML specified, and '--config' and SPLUNK_CONFIG no specified.
173+
// Sets '--config' to default config file path if '--config', SPLUNK_CONFIG and SPLUNK_CONFIG_YAML not specified.
174+
func checkConfig() {
175+
configPathFlagExists, configPathFlag := getKeyValue(os.Args[1:], "--config")
176+
configPathVar := os.Getenv(configEnvVarName)
177+
configYaml := os.Getenv(configYamlEnvVarName)
178+
179+
if configPathFlagExists && configPathFlag == "" {
180+
log.Fatal("Command line flag --config specified but empty")
181+
}
182+
183+
if configPathFlag != "" {
184+
if _, err := os.Stat(configPathFlag); err != nil {
185+
log.Fatalf("Unable to find the configuration file (%s) ensure flag '--config' is set properly", configPathFlag)
193186
}
194-
_, err = os.Stat(defaultLocalSAPMConfig)
195-
if err == nil {
196-
config = defaultLocalSAPMConfig
187+
188+
if configPathVar != "" && configPathVar != configPathFlag {
189+
log.Printf("Both environment variable %v and flag '--config' were specified. Using the flag value %s and ignoring the environment variable value %s in this session", configEnvVarName, configPathFlag, configPathVar)
197190
}
198-
if config == "" {
199-
log.Fatalf("Unable to find the default configuration file, ensure %s environment variable is set properly", configEnvVarName)
191+
192+
if configYaml != "" {
193+
log.Printf("Both environment variable %s and flag '--config' were specified. Using the flag value %s and ignoring the environment variable in this session", configYamlEnvVarName, configPathFlag)
200194
}
201-
} else {
202-
// Check if file exists.
203-
_, err := os.Stat(config)
204-
if err != nil {
205-
log.Fatalf("Unable to find the configuration file (%s) ensure %s environment variable is set properly", config, configEnvVarName)
195+
196+
checkRequiredEnvVars(configPathFlag)
197+
198+
log.Printf("Set config to %v", configPathFlag)
199+
return
200+
}
201+
202+
if configPathVar != "" {
203+
if _, err := os.Stat(configPathVar); err != nil {
204+
log.Fatalf("Unable to find the configuration file (%s) ensure %s environment variable is set properly", configPathVar, configEnvVarName)
205+
}
206+
207+
os.Args = append(os.Args, "--config="+configPathVar)
208+
209+
if configYaml != "" {
210+
log.Printf("Both %s and %s were specified. Using %s environment variable value %s for this session", configEnvVarName, configYamlEnvVarName, configEnvVarName, configPathVar)
206211
}
212+
213+
checkRequiredEnvVars(configPathVar)
214+
215+
log.Printf("Set config to %v", configPathVar)
216+
return
217+
}
218+
219+
if configYaml != "" {
220+
log.Printf("Using environment variable %s for configuration", configYamlEnvVarName)
221+
return
222+
}
223+
224+
defaultConfigPath := getExistingDefaultConfigPath()
225+
checkRequiredEnvVars(defaultConfigPath)
226+
os.Args = append(os.Args, "--config="+defaultConfigPath)
227+
log.Printf("Set config to %v", defaultConfigPath)
228+
}
229+
230+
func getExistingDefaultConfigPath() (path string) {
231+
if _, err := os.Stat(defaultLocalSAPMConfig); err == nil {
232+
return defaultLocalSAPMConfig
233+
}
234+
if _, err := os.Stat(defaultDockerSAPMConfig); err == nil {
235+
return defaultDockerSAPMConfig
207236
}
237+
log.Fatalf("Unable to find the default configuration file (%s) or (%s)", defaultLocalSAPMConfig, defaultDockerSAPMConfig)
238+
return
239+
}
208240

209-
switch config {
241+
func checkRequiredEnvVars(path string) {
242+
// Check environment variables required by default configuration.
243+
switch path {
210244
case
211245
defaultDockerSAPMConfig,
212246
defaultDockerOTLPConfig,
213247
defaultLocalSAPMConfig,
214248
defaultLocalOTLPConfig:
215-
// The following environment variables are required.
216-
// If any are missing stop here.
217249
requiredEnvVars := []string{realmEnvVarName, tokenEnvVarName}
218250
for _, v := range requiredEnvVars {
219251
if len(os.Getenv(v)) == 0 {
220252
log.Printf("Usage: %s=12345 %s=us0 %s", tokenEnvVarName, realmEnvVarName, os.Args[0])
221-
log.Fatalf("ERROR: Missing required environment variable %s with default config path %s", v, config)
253+
log.Fatalf("ERROR: Missing required environment variable %s with default config path %s", v, path)
222254
}
223255
}
224256
}
225-
226-
args := os.Args[1:]
227-
if !contains(args, "--config") {
228-
// Inject the command line flag that controls the configuration.
229-
os.Args = append(os.Args, "--config="+config)
230-
}
231-
log.Printf("Set config to %v", config)
232257
}
233258

234259
// Validate and set the memory ballast
@@ -277,7 +302,7 @@ func setMemoryLimit(memTotalSizeMiB int) {
277302

278303
// Validate memoryLimit is sane
279304
args := os.Args[1:]
280-
b := getKeyValue(args, "--mem-ballast-size-mib")
305+
_, b := getKeyValue(args, "--mem-ballast-size-mib")
281306
ballastSize, _ := strconv.Atoi(b)
282307
if (ballastSize * 2) > memLimit {
283308
log.Fatalf("Memory limit (%v) is less than 2x ballast (%v). Increase memory limit or decrease ballast size.", memLimit, ballastSize)
@@ -287,6 +312,19 @@ func setMemoryLimit(memTotalSizeMiB int) {
287312
log.Printf("Set memory limit to %d MiB", memLimit)
288313
}
289314

315+
// Returns a ParserProvider that reads configuration YAML from an environment variable when applicable.
316+
func newBaseParserProvider() parserprovider.ParserProvider {
317+
_, configPathFlag := getKeyValue(os.Args[1:], "--config")
318+
configPathVar := os.Getenv(configEnvVarName)
319+
configYaml := os.Getenv(configYamlEnvVarName)
320+
321+
if configPathFlag == "" && configPathVar == "" && configYaml != "" {
322+
return parserprovider.NewInMemory(bytes.NewBufferString(configYaml))
323+
}
324+
325+
return parserprovider.Default()
326+
}
327+
290328
func runInteractive(params service.CollectorSettings) error {
291329
app, err := service.New(params)
292330
if err != nil {

0 commit comments

Comments
 (0)