Skip to content

Commit de78570

Browse files
fix: allow OTEL_CONFIG_OVERRIDES env var to replace agent config overrides (#132)
### Description OB-38640 allow OTEL_CONFIG_OVERRIDES env var to replace agent config overrides This will allow the agent to be fully run with env variables only. example: ```sh $ OTEL_CONFIG_OVERRIDES=`cat tmp.yml` ./observe-agent config # ======== computed agent config host_monitoring: enabled: true logs: enabled: true include: [] metrics: host: enabled: true process: enabled: false observe_url: "" otelconfigfile: "" self_monitoring: enabled: true token: "" # ======== config file /var/folders/y8/v7cyk9611qbg059c0q02vk0w0000gn/T/observe-agent2529970453/otel-config-overrides-4110568018.yaml processors: probabilistic_sampler: sampling_percentage: 50 service: pipelines: logs/forward: exporters: - debug processors: - probabilistic_sampler receivers: - otlp ``` ### Checklist - [ ] Created tests which fail without the change (if possible) - [ ] Extended the README / documentation, if necessary
1 parent 0fae294 commit de78570

File tree

3 files changed

+44
-21
lines changed

3 files changed

+44
-21
lines changed

internal/commands/config/config.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,9 @@ OTEL configuration.`,
4141
fmt.Printf("# ======== computed agent config\n")
4242
fmt.Println(string(viperConfigYaml) + "\n")
4343
agentConfig := viper.ConfigFileUsed()
44-
configFilePaths = append([]string{agentConfig}, configFilePaths...)
44+
if agentConfig != "" {
45+
configFilePaths = append([]string{agentConfig}, configFilePaths...)
46+
}
4547
for _, filePath := range configFilePaths {
4648
file, err := os.ReadFile(filePath)
4749
if err != nil {

internal/commands/start/start.go

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,10 @@ func SetupAndGetConfigFiles(ctx context.Context) ([]string, func(), error) {
2727
if err != nil {
2828
return nil, nil, err
2929
}
30-
configFilePaths, overridePath, err := connections.GetAllOtelConfigFilePaths(ctx, tmpDir)
3130
cleanup := func() {
32-
if overridePath != "" {
33-
os.Remove(overridePath)
34-
}
3531
os.RemoveAll(tmpDir)
3632
}
33+
configFilePaths, err := connections.GetAllOtelConfigFilePaths(ctx, tmpDir)
3734
if err != nil {
3835
cleanup()
3936
return nil, nil, err

internal/connections/confighandler.go

Lines changed: 40 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -11,30 +11,34 @@ import (
1111
logger "github.com/observeinc/observe-agent/internal/commands/util"
1212
"github.com/observeinc/observe-agent/internal/config"
1313
"github.com/spf13/viper"
14+
"gopkg.in/yaml.v3"
1415
)
1516

16-
func GetAllOtelConfigFilePaths(ctx context.Context, tmpDir string) ([]string, string, error) {
17+
const (
18+
OTEL_OVERRIDE_YAML_KEY = "otel_config_overrides"
19+
)
20+
21+
func GetAllOtelConfigFilePaths(ctx context.Context, tmpDir string) ([]string, error) {
1722
configFilePaths := []string{}
1823
// If the default otel-collector.yaml exists, add it to the list of config files
1924
defaultOtelConfigPath := filepath.Join(GetDefaultConfigFolder(), "otel-collector.yaml")
2025
if _, err := os.Stat(defaultOtelConfigPath); err == nil {
2126
agentConf, err := config.AgentConfigFromViper(viper.GetViper())
2227
if err != nil {
23-
return nil, "", err
28+
return nil, err
2429
}
2530
otelConfigRendered, err := RenderConfigTemplate(ctx, tmpDir, defaultOtelConfigPath, agentConf)
2631
if err != nil {
27-
return nil, "", err
32+
return nil, err
2833
}
2934
configFilePaths = append(configFilePaths, otelConfigRendered)
3035
}
31-
var err error
3236
// Get additional config paths based on connection configs
3337
for _, conn := range AllConnectionTypes {
3438
if viper.IsSet(conn.Name) {
3539
connectionPaths, err := conn.GetConfigFilePaths(ctx, tmpDir)
3640
if err != nil {
37-
return nil, "", err
41+
return nil, err
3842
}
3943
configFilePaths = append(configFilePaths, connectionPaths...)
4044
}
@@ -44,16 +48,32 @@ func GetAllOtelConfigFilePaths(ctx context.Context, tmpDir string) ([]string, st
4448
configFilePaths = append(configFilePaths, viper.GetString("otelConfigFile"))
4549
}
4650
// Generate override file and include path if overrides provided
47-
var overridePath string
48-
if viper.IsSet("otel_config_overrides") {
49-
overridePath, err = GetOverrideConfigFile(viper.Sub("otel_config_overrides"))
50-
if err != nil {
51-
return configFilePaths, overridePath, err
51+
if viper.IsSet(OTEL_OVERRIDE_YAML_KEY) {
52+
// GetStringMap is more lenient with respect to conversions than Sub, which only handles maps.
53+
overrides := viper.GetStringMap(OTEL_OVERRIDE_YAML_KEY)
54+
if len(overrides) == 0 {
55+
stringData := viper.GetString(OTEL_OVERRIDE_YAML_KEY)
56+
// If this was truly set to empty, then ignore it.
57+
if stringData != "" {
58+
// Viper can handle overrides set in the agent config, or passed in as an env var as a JSON string.
59+
// For consistency, we also want to accept an env var as a YAML string.
60+
err := yaml.Unmarshal([]byte(stringData), &overrides)
61+
if err != nil {
62+
return nil, fmt.Errorf("%s was provided but could not be parsed", OTEL_OVERRIDE_YAML_KEY)
63+
}
64+
}
65+
}
66+
// Only create the config file if there are overrides present (ie ignore empty maps)
67+
if len(overrides) != 0 {
68+
overridePath, err := GetOverrideConfigFile(tmpDir, overrides)
69+
if err != nil {
70+
return nil, err
71+
}
72+
configFilePaths = append(configFilePaths, overridePath)
5273
}
53-
configFilePaths = append(configFilePaths, overridePath)
5474
}
5575
logger.FromCtx(ctx).Debug(fmt.Sprint("Config file paths:", configFilePaths))
56-
return configFilePaths, overridePath, nil
76+
return configFilePaths, nil
5777
}
5878

5979
func SetEnvVars() error {
@@ -75,14 +95,18 @@ func SetEnvVars() error {
7595
return nil
7696
}
7797

78-
func GetOverrideConfigFile(sub *viper.Viper) (string, error) {
79-
f, err := os.CreateTemp("", "otel-config-overrides-*.yaml")
98+
func GetOverrideConfigFile(tmpDir string, data map[string]any) (string, error) {
99+
f, err := os.CreateTemp(tmpDir, "otel-config-overrides-*.yaml")
80100
if err != nil {
81101
return "", fmt.Errorf("failed to create config file to write to: %w", err)
82102
}
83-
err = sub.WriteConfigAs(f.Name())
103+
contents, err := yaml.Marshal(data)
104+
if err != nil {
105+
return "", fmt.Errorf("failed to marshal otel config overrides: %w", err)
106+
}
107+
_, err = f.Write([]byte(contents))
84108
if err != nil {
85-
return f.Name(), fmt.Errorf("failed to write otel config overrides to file: %w", err)
109+
return "", fmt.Errorf("failed to write otel config overrides to file: %w", err)
86110
}
87111
return f.Name(), nil
88112
}

0 commit comments

Comments
 (0)