Skip to content

Commit 4cb0245

Browse files
authored
Add platform-specific default configs (#2212)
1 parent 43f2526 commit 4cb0245

17 files changed

Lines changed: 1011 additions & 15 deletions

tool/downloader/downloader.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ func RunDownloader(mode, downloadLocation, outputDir, inputConfig, multiConfig s
105105
case locationDefault:
106106
if len(locationArray) == 2 {
107107
name := locationArray[1]
108-
cfg, ok := translatorconfig.DefaultJSONConfigFor(name)
108+
cfg, ok := translatorconfig.DefaultJSONConfigFor(name, util.DetectKubernetesMode(mode) != "", util.DetectECS())
109109
if !ok {
110110
return fmt.Errorf("unknown default config %q", name)
111111
}

tool/downloader/downloader_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ func TestRunDownloader_DefaultOtel(t *testing.T) {
2323
content, err := os.ReadFile(filepath.Join(outputDir, "default_otel.tmp"))
2424
require.NoError(t, err)
2525

26-
expected, ok := config.DefaultJSONConfigFor("otel")
26+
expected, ok := config.DefaultJSONConfigFor("otel", false, false)
2727
require.True(t, ok)
2828
assert.JSONEq(t, expected, string(content))
2929
}

translator/cmdutil/translatorutil_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -439,7 +439,7 @@ func TestOpenTelemetryResourceAttributesSchemaValidation(t *testing.T) {
439439
}
440440

441441
func TestDefaultOtelConfigSchemaValidation(t *testing.T) {
442-
cfg, ok := config.DefaultJSONConfigFor("otel")
442+
cfg, ok := config.DefaultJSONConfigFor("otel", false, false)
443443
require.True(t, ok)
444444
jsonMap, err := util.GetJsonMapFromJsonBytes([]byte(cfg))
445445
require.NoError(t, err)

translator/config/defaultConfig.go

Lines changed: 50 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,59 @@
33

44
package config
55

6+
import _ "embed"
7+
8+
// Platform-specific default configs. Unlike otel.json/otel_windows.json (which
9+
// are OS-build-tagged), these have no OS constraint - K8s/ECS are Linux - so
10+
// they live here rather than in a build-tagged file.
11+
//
12+
//go:embed defaults/otel_ecs.json
13+
var defaultOtelECSConfig string
14+
15+
//go:embed defaults/otel_k8s.json
16+
var defaultOtelK8sConfig string
17+
18+
// otelConfigName is the shared map key for the otel default config and its
19+
// platform variants (e.g. -c default:otel).
20+
const otelConfigName = "otel"
21+
22+
// defaultConfigs holds the base configs addressable by name.
623
var defaultConfigs = map[string]string{
7-
"otel": defaultOtelConfig,
24+
otelConfigName: defaultOtelConfig,
825
}
926

10-
// DefaultJSONConfigFor returns the named default config if it exists.
11-
func DefaultJSONConfigFor(name string) (string, bool) {
27+
// platform enumerates the environments that get a platform-specific default
28+
// config variant. VMs (EC2, Azure VM) use the base config; K8s and ECS get
29+
// their own variants since host-level scraping inside a container reports the
30+
// container, not the host.
31+
type platform int
32+
33+
const (
34+
platformK8s platform = iota
35+
platformECS
36+
)
37+
38+
// platformConfigs holds the platform variants. Kept out of defaultConfigs so
39+
// they are NOT addressable by name (e.g. -c default:otel_ecs on a VM).
40+
var platformConfigs = map[platform]map[string]string{
41+
platformK8s: {otelConfigName: defaultOtelK8sConfig},
42+
platformECS: {otelConfigName: defaultOtelECSConfig},
43+
}
44+
45+
// DefaultJSONConfigFor returns the platform-specific variant when the caller's
46+
// detected platform has one, falling back to the named base config otherwise.
47+
// Kubernetes takes precedence over ECS.
48+
func DefaultJSONConfigFor(name string, isKubernetes, isECS bool) (string, bool) {
49+
switch {
50+
case isKubernetes:
51+
if cfg, ok := platformConfigs[platformK8s][name]; ok {
52+
return cfg, true
53+
}
54+
case isECS:
55+
if cfg, ok := platformConfigs[platformECS][name]; ok {
56+
return cfg, true
57+
}
58+
}
1259
cfg, ok := defaultConfigs[name]
1360
return cfg, ok
1461
}

translator/config/defaultConfig_test.go

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,17 +11,60 @@ import (
1111
)
1212

1313
func TestDefaultJSONConfigFor_Otel(t *testing.T) {
14-
cfg, ok := DefaultJSONConfigFor("otel")
14+
cfg, ok := DefaultJSONConfigFor("otel", false, false)
1515
require.True(t, ok)
1616
assert.JSONEq(t, defaultOtelConfig, cfg)
1717
}
1818

1919
func TestDefaultJSONConfigFor_Unknown(t *testing.T) {
20-
_, ok := DefaultJSONConfigFor("unknown")
20+
_, ok := DefaultJSONConfigFor("unknown", false, false)
2121
assert.False(t, ok)
2222
}
2323

2424
func TestDefaultJSONConfigFor_Empty(t *testing.T) {
25-
_, ok := DefaultJSONConfigFor("")
25+
_, ok := DefaultJSONConfigFor("", false, false)
26+
assert.False(t, ok)
27+
}
28+
29+
func TestDefaultJSONConfigFor_PlatformVariantsNotAddressableByName(t *testing.T) {
30+
// The variant suffixes must not be resolvable as base config names, even
31+
// when a platform is detected (e.g. -c default:otel_ecs on any host). The
32+
// variants are only reachable via the platform flags on the base name.
33+
_, ok := DefaultJSONConfigFor("otel_ecs", false, true)
34+
assert.False(t, ok)
35+
_, ok = DefaultJSONConfigFor("otel_k8s", true, false)
36+
assert.False(t, ok)
37+
}
38+
39+
func TestDefaultJSONConfigFor_OtelK8s(t *testing.T) {
40+
cfg, ok := DefaultJSONConfigFor("otel", true, false)
41+
require.True(t, ok)
42+
assert.JSONEq(t, defaultOtelK8sConfig, cfg)
43+
assert.Contains(t, cfg, "container_insights")
44+
assert.NotContains(t, cfg, "host_metrics")
45+
}
46+
47+
func TestDefaultJSONConfigFor_OtelECS(t *testing.T) {
48+
cfg, ok := DefaultJSONConfigFor("otel", false, true)
49+
require.True(t, ok)
50+
assert.JSONEq(t, defaultOtelECSConfig, cfg)
51+
assert.NotContains(t, cfg, "host_metrics")
52+
assert.NotContains(t, cfg, "container_insights")
53+
}
54+
55+
func TestDefaultJSONConfigFor_KubernetesTakesPrecedenceOverECS(t *testing.T) {
56+
cfg, ok := DefaultJSONConfigFor("otel", true, true)
57+
require.True(t, ok)
58+
assert.JSONEq(t, defaultOtelK8sConfig, cfg)
59+
}
60+
61+
func TestDefaultJSONConfigFor_VMFallsBackToBase(t *testing.T) {
62+
cfg, ok := DefaultJSONConfigFor("otel", false, false)
63+
require.True(t, ok)
64+
assert.JSONEq(t, defaultOtelConfig, cfg)
65+
}
66+
67+
func TestDefaultJSONConfigFor_UnknownWithPlatform(t *testing.T) {
68+
_, ok := DefaultJSONConfigFor("unknown", true, false)
2669
assert.False(t, ok)
2770
}

translator/config/defaults/otel.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
},
77
"opentelemetry": {
88
"collect": {
9+
"host_metrics": {},
910
"otlp": {
1011
"span_metrics_enabled": true
1112
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"agent": {
3+
"credentials": {
4+
"role_arn": "${CWAGENT_ROLE_ARN}"
5+
}
6+
},
7+
"opentelemetry": {
8+
"collect": {
9+
"otlp": {
10+
"span_metrics_enabled": true
11+
}
12+
}
13+
}
14+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"agent": {
3+
"credentials": {
4+
"role_arn": "${CWAGENT_ROLE_ARN}"
5+
}
6+
},
7+
"opentelemetry": {
8+
"collect": {
9+
"container_insights": {},
10+
"otlp": {
11+
"span_metrics_enabled": true
12+
}
13+
}
14+
}
15+
}

translator/config/defaults/otel_windows.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
},
77
"opentelemetry": {
88
"collect": {
9+
"host_metrics": {},
910
"otlp": {},
1011
"windows_events": {
1112
"collect_list": [

translator/jsonconfig/mergeJsonConfig.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import (
1111
"github.com/aws/amazon-cloudwatch-agent/internal/constants"
1212
"github.com/aws/amazon-cloudwatch-agent/translator"
1313
"github.com/aws/amazon-cloudwatch-agent/translator/config"
14+
"github.com/aws/amazon-cloudwatch-agent/translator/context"
1415
"github.com/aws/amazon-cloudwatch-agent/translator/jsonconfig/mergeJsonUtil"
1516
_ "github.com/aws/amazon-cloudwatch-agent/translator/registerrules"
1617
"github.com/aws/amazon-cloudwatch-agent/translator/util"
@@ -26,7 +27,7 @@ func MergeJsonConfigMaps(jsonConfigMapMap map[string]map[string]interface{}, def
2627
log.Println("No json config files found, use the default ecs config")
2728
return util.GetJsonMapFromJsonBytes([]byte(config.DefaultECSJsonConfig()))
2829
}
29-
} else if cfg, ok := config.DefaultJSONConfigFor(useDefault); ok {
30+
} else if cfg, ok := config.DefaultJSONConfigFor(useDefault, context.CurrentContext().KubernetesMode() != "", util.DetectECS()); ok {
3031
log.Printf("No json config files found, use the default %s config", useDefault)
3132
return util.GetJsonMapFromJsonBytes([]byte(cfg))
3233
}

0 commit comments

Comments
 (0)