diff --git a/cmd/amazon-cloudwatch-agent/amazon-cloudwatch-agent.go b/cmd/amazon-cloudwatch-agent/amazon-cloudwatch-agent.go index 8e4a49a5a7..3a87fc58c4 100644 --- a/cmd/amazon-cloudwatch-agent/amazon-cloudwatch-agent.go +++ b/cmd/amazon-cloudwatch-agent/amazon-cloudwatch-agent.go @@ -494,7 +494,7 @@ func main() { flag.Var(&fOtelConfigs, configprovider.OtelConfigFlagName, "YAML configuration files to run OTel pipeline") flag.Parse() if len(fOtelConfigs) == 0 { - _ = fOtelConfigs.Set(paths.YamlConfigPath) + _ = fOtelConfigs.Set(getFallbackOtelConfig(*fTomlConfig, paths.YamlConfigPath)) } args := flag.Args() sectionFilters, inputFilters, outputFilters := []string{}, []string{}, []string{} @@ -743,3 +743,28 @@ func checkRightForBinariesFileWithInputPlugins(inputPlugins []string) (string, e return "", nil } + +// getFallbackOtelConfig returns the first fallback YAML file that exists. It checks files in the following order: +// 1. Default YAML path +// 2. Default YAML in the provided TOML directory +// 3. YAML with the same name as the provided TOML +func getFallbackOtelConfig(tomlPath, defaultYamlPath string) string { + candidatePaths := []string{defaultYamlPath} + if tomlPath != "" { + tomlDir := filepath.Dir(tomlPath) + samePathYAML := strings.TrimSuffix(tomlPath, filepath.Ext(tomlPath)) + ".yaml" + candidatePaths = append(candidatePaths, + filepath.Join(tomlDir, paths.YAML), + samePathYAML, + ) + } + fallbackPath := defaultYamlPath + for _, candidatePath := range candidatePaths { + _, err := os.Stat(candidatePath) + if err == nil { + fallbackPath = candidatePath + break + } + } + return fallbackPath +} diff --git a/cmd/amazon-cloudwatch-agent/amazon-cloudwatch-agent_test.go b/cmd/amazon-cloudwatch-agent/amazon-cloudwatch-agent_test.go index cef6b7a06f..548ba239a6 100644 --- a/cmd/amazon-cloudwatch-agent/amazon-cloudwatch-agent_test.go +++ b/cmd/amazon-cloudwatch-agent/amazon-cloudwatch-agent_test.go @@ -20,6 +20,7 @@ import ( "github.com/aws/amazon-cloudwatch-agent/cfg/envconfig" "github.com/aws/amazon-cloudwatch-agent/internal/merge/confmap" "github.com/aws/amazon-cloudwatch-agent/logger" + "github.com/aws/amazon-cloudwatch-agent/tool/paths" ) func Test_getCollectorParams(t *testing.T) { @@ -154,6 +155,52 @@ service: } } +func TestFallbackOtelConfig(t *testing.T) { + defaultYamlRelativePath := filepath.Join("default", paths.YAML) + testCases := map[string]struct { + tomlRelativePath string + filesToCreate []string + want string + }{ + "WithoutAnyFiles": { + tomlRelativePath: filepath.Join("config", "config.toml"), + want: defaultYamlRelativePath, + }, + "WithDefaultYamlPath": { + tomlRelativePath: filepath.Join("config", "config.toml"), + filesToCreate: []string{defaultYamlRelativePath, filepath.Join("config", paths.YAML)}, + want: defaultYamlRelativePath, + }, + "WithDefaultYamlInTomlDir": { + tomlRelativePath: filepath.Join("config", "config.toml"), + filesToCreate: []string{filepath.Join("config", paths.YAML), filepath.Join("config", "config.yaml")}, + want: filepath.Join("config", paths.YAML), + }, + "WithSameNameAsToml": { + tomlRelativePath: filepath.Join("config", "config.toml"), + filesToCreate: []string{filepath.Join("config", "config.yaml")}, + want: filepath.Join("config", "config.yaml"), + }, + "WithoutTomlPath": { + tomlRelativePath: "", + filesToCreate: []string{filepath.Join("config", "config.yaml")}, + want: defaultYamlRelativePath, + }, + } + for name, testCase := range testCases { + t.Run(name, func(t *testing.T) { + tmpDir := t.TempDir() + for _, fileToCreate := range testCase.filesToCreate { + path := filepath.Join(tmpDir, fileToCreate) + require.NoError(t, os.MkdirAll(filepath.Dir(path), 0755)) + require.NoError(t, os.WriteFile(path, nil, 0600)) + } + got := getFallbackOtelConfig(filepath.Join(tmpDir, testCase.tomlRelativePath), filepath.Join(tmpDir, defaultYamlRelativePath)) + assert.Equal(t, filepath.Join(tmpDir, testCase.want), got) + }) + } +} + func mustLoadFromFile(t *testing.T, path string) *confmap.Conf { conf, err := confmap.NewFileLoader(path).Load() require.NoError(t, err) diff --git a/service/configprovider/flags.go b/service/configprovider/flags.go index dc62bd2920..13ec002066 100644 --- a/service/configprovider/flags.go +++ b/service/configprovider/flags.go @@ -4,6 +4,7 @@ package configprovider import ( + "flag" "fmt" ) @@ -13,6 +14,8 @@ const ( type OtelConfigFlags []string +var _ flag.Value = (*OtelConfigFlags)(nil) + func (o *OtelConfigFlags) String() string { return fmt.Sprint(*o) }