From 90caaca5427b09486ba1ef369e5b4563ccfddb85 Mon Sep 17 00:00:00 2001 From: Lisa Guo Date: Fri, 1 Mar 2024 14:28:45 -0500 Subject: [PATCH] Add kubernetes modes and use eksdetector on startup (#1058) --- cmd/config-translator/translator.go | 5 ++- .../internal/resolver/kubernetes.go | 4 +- .../internal/resolver/kubernetes_test.go | 12 +++--- translator/config/mode.go | 15 +++++-- translator/context/context.go | 23 ++++++++++- .../appsignals_and_eks_config.yaml | 4 +- .../appsignals_and_k8s_config.yaml | 4 +- translator/tocwconfig/tocwconfig_test.go | 25 +++++++---- .../otel/exporter/awsemf/translator.go | 15 ++++--- .../otel/exporter/awsemf/translator_test.go | 39 ++++++------------ .../otel/exporter/awsxray/translator.go | 21 ++++------ .../otel/exporter/awsxray/translator_test.go | 33 ++++++--------- .../pipeline/appsignals/translator_test.go | 41 ++++++++++--------- .../processor/awsappsignals/translator.go | 30 +++++++------- .../awsappsignals/translator_test.go | 35 +++++++--------- .../translate/otel/translate_otel_test.go | 25 +++++------ .../eksdetector}/eksdetector.go | 2 +- .../eksdetector}/eksdetector_test.go | 2 +- .../eksdetector}/eksdetectortestutil.go | 2 +- translator/util/sdkutil.go | 26 ++++++++++++ translator/util/sdkutil_test.go | 24 +++++++++++ 21 files changed, 225 insertions(+), 162 deletions(-) rename translator/{translate/otel/common => util/eksdetector}/eksdetector.go (99%) rename translator/{translate/otel/common => util/eksdetector}/eksdetector_test.go (99%) rename translator/{translate/otel/common => util/eksdetector}/eksdetectortestutil.go (98%) diff --git a/cmd/config-translator/translator.go b/cmd/config-translator/translator.go index da9124803d..2d69a2c03c 100644 --- a/cmd/config-translator/translator.go +++ b/cmd/config-translator/translator.go @@ -61,7 +61,10 @@ func initFlags() { } translatorUtil.SetProxyEnv(ctx.Proxy()) translatorUtil.SetSSLEnv(ctx.SSL()) - ctx.SetMode(translatorUtil.DetectAgentMode(*inputMode)) + + mode := translatorUtil.DetectAgentMode(*inputMode) + ctx.SetMode(mode) + ctx.SetKubernetesMode(translatorUtil.DetectKubernetesMode(mode)) } /** diff --git a/plugins/processors/awsappsignals/internal/resolver/kubernetes.go b/plugins/processors/awsappsignals/internal/resolver/kubernetes.go index a38261820d..a87d8fdc0a 100644 --- a/plugins/processors/awsappsignals/internal/resolver/kubernetes.go +++ b/plugins/processors/awsappsignals/internal/resolver/kubernetes.go @@ -26,7 +26,7 @@ import ( "k8s.io/client-go/tools/clientcmd" attr "github.com/aws/amazon-cloudwatch-agent/plugins/processors/awsappsignals/internal/attributes" - "github.com/aws/amazon-cloudwatch-agent/translator/translate/otel/common" + "github.com/aws/amazon-cloudwatch-agent/translator/util/eksdetector" ) const ( @@ -680,7 +680,7 @@ func (h *kubernetesHostedInAttributeResolver) Process(attributes, resourceAttrib } } - if isEks := common.IsEKS(); isEks.Value { + if isEks := eksdetector.IsEKS(); isEks.Value { attributes.PutStr(attr.HostedInClusterNameEKS, h.clusterName) } else { attributes.PutStr(attr.HostedInClusterNameK8s, h.clusterName) diff --git a/plugins/processors/awsappsignals/internal/resolver/kubernetes_test.go b/plugins/processors/awsappsignals/internal/resolver/kubernetes_test.go index fcdd7ad0b2..c21b8ee2ab 100644 --- a/plugins/processors/awsappsignals/internal/resolver/kubernetes_test.go +++ b/plugins/processors/awsappsignals/internal/resolver/kubernetes_test.go @@ -19,7 +19,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" attr "github.com/aws/amazon-cloudwatch-agent/plugins/processors/awsappsignals/internal/attributes" - "github.com/aws/amazon-cloudwatch-agent/translator/translate/otel/common" + "github.com/aws/amazon-cloudwatch-agent/translator/util/eksdetector" ) // MockDeleter deletes a key immediately, useful for testing. @@ -817,8 +817,8 @@ func TestEksResolver(t *testing.T) { } func TestHostedInEksResolver(t *testing.T) { - common.NewDetector = common.TestEKSDetector - common.IsEKS = common.TestIsEKSCacheEKS + eksdetector.NewDetector = eksdetector.TestEKSDetector + eksdetector.IsEKS = eksdetector.TestIsEKSCacheEKS // helper function to get string values from the attributes getStrAttr := func(attributes pcommon.Map, key string, t *testing.T) string { if value, ok := attributes.Get(key); ok { @@ -850,8 +850,8 @@ func TestHostedInEksResolver(t *testing.T) { } func TestHostedInNativeK8sEC2Resolver(t *testing.T) { - common.NewDetector = common.TestK8sDetector - common.IsEKS = common.TestIsEKSCacheK8s + eksdetector.NewDetector = eksdetector.TestK8sDetector + eksdetector.IsEKS = eksdetector.TestIsEKSCacheK8s // helper function to get string values from the attributes getStrAttr := func(attributes pcommon.Map, key string, t *testing.T) string { if value, ok := attributes.Get(key); ok { @@ -883,7 +883,7 @@ func TestHostedInNativeK8sEC2Resolver(t *testing.T) { } func TestHostedInNativeK8sOnPremResolver(t *testing.T) { - common.NewDetector = common.TestK8sDetector + eksdetector.NewDetector = eksdetector.TestK8sDetector // helper function to get string values from the attributes getStrAttr := func(attributes pcommon.Map, key string, t *testing.T) string { if value, ok := attributes.Get(key); ok { diff --git a/translator/config/mode.go b/translator/config/mode.go index 95638ba471..a5cb44f492 100644 --- a/translator/config/mode.go +++ b/translator/config/mode.go @@ -11,7 +11,16 @@ const ( ) const ( - ShortModeEC2 = "EC2" - ShortModeOnPrem = "OP" - ShortModeWithIRSA = "WI" + ModeEKS = "EKS" + ModeK8sEC2 = "K8sEC2" + ModeK8sOnPrem = "K8sOnPrem" +) + +const ( + ShortModeEC2 = "EC2" + ShortModeOnPrem = "OP" + ShortModeWithIRSA = "WI" + ShortModeEKS = "EKS" + ShortModeK8sEC2 = "K8E" + ShortModeK8sOnPrem = "K8OP" ) diff --git a/translator/context/context.go b/translator/context/context.go index 9dcc7ae7a1..30091ce399 100644 --- a/translator/context/context.go +++ b/translator/context/context.go @@ -41,6 +41,7 @@ type Context struct { multiConfig string outputTomlFilePath string mode string + kubernetesMode string shortMode string credentials map[string]string proxy map[string]string @@ -97,6 +98,10 @@ func (ctx *Context) Mode() string { return ctx.mode } +func (ctx *Context) KubernetesMode() string { + return ctx.kubernetesMode +} + func (ctx *Context) ShortMode() string { return ctx.shortMode } @@ -128,7 +133,23 @@ func (ctx *Context) SetMode(mode string) { ctx.mode = config.ModeWithIRSA ctx.shortMode = config.ShortModeWithIRSA default: - log.Panicf("Invalid mode %s. Valid mode values are %s, %s, %s and %s.", mode, config.ModeEC2, config.ModeOnPrem, config.ModeOnPremise, config.ModeWithIRSA) + log.Panicf("Invalid mode %s. Valid mode values are %s, %s, %s, and %s.", mode, config.ModeEC2, config.ModeOnPrem, config.ModeOnPremise, config.ModeWithIRSA) + } +} + +func (ctx *Context) SetKubernetesMode(mode string) { + switch mode { + case config.ModeEKS: + ctx.kubernetesMode = config.ModeEKS + ctx.shortMode = config.ShortModeEKS + case config.ModeK8sEC2: + ctx.kubernetesMode = config.ModeK8sEC2 + ctx.shortMode = config.ShortModeK8sEC2 + case config.ModeK8sOnPrem: + ctx.kubernetesMode = config.ModeK8sOnPrem + ctx.shortMode = config.ShortModeK8sOnPrem + default: + ctx.kubernetesMode = "" } } diff --git a/translator/tocwconfig/sampleConfig/appsignals_and_eks_config.yaml b/translator/tocwconfig/sampleConfig/appsignals_and_eks_config.yaml index 6b54e0320a..007f2a2eaf 100644 --- a/translator/tocwconfig/sampleConfig/appsignals_and_eks_config.yaml +++ b/translator/tocwconfig/sampleConfig/appsignals_and_eks_config.yaml @@ -287,7 +287,7 @@ extensions: operations: - PutLogEvents usage_flags: - mode: EC2 + mode: EKS region_type: ACJ agenthealth/traces: is_usage_data_enabled: true @@ -295,7 +295,7 @@ extensions: operations: - PutTraceSegments usage_flags: - mode: EC2 + mode: EKS region_type: ACJ awsproxy/app_signals: aws_endpoint: "" diff --git a/translator/tocwconfig/sampleConfig/appsignals_and_k8s_config.yaml b/translator/tocwconfig/sampleConfig/appsignals_and_k8s_config.yaml index 8c33dbac40..25beb4228a 100644 --- a/translator/tocwconfig/sampleConfig/appsignals_and_k8s_config.yaml +++ b/translator/tocwconfig/sampleConfig/appsignals_and_k8s_config.yaml @@ -287,7 +287,7 @@ extensions: operations: - PutLogEvents usage_flags: - mode: EC2 + mode: K8E region_type: ACJ agenthealth/traces: is_usage_data_enabled: true @@ -295,7 +295,7 @@ extensions: operations: - PutTraceSegments usage_flags: - mode: EC2 + mode: K8E region_type: ACJ awsproxy/app_signals: aws_endpoint: "" diff --git a/translator/tocwconfig/tocwconfig_test.go b/translator/tocwconfig/tocwconfig_test.go index 42712d5e92..22ba8134ac 100644 --- a/translator/tocwconfig/tocwconfig_test.go +++ b/translator/tocwconfig/tocwconfig_test.go @@ -23,7 +23,6 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "gopkg.in/yaml.v3" - "k8s.io/client-go/kubernetes/fake" "github.com/aws/amazon-cloudwatch-agent/cfg/commonconfig" "github.com/aws/amazon-cloudwatch-agent/cfg/envconfig" @@ -39,6 +38,7 @@ import ( "github.com/aws/amazon-cloudwatch-agent/translator/translate/agent" "github.com/aws/amazon-cloudwatch-agent/translator/translate/otel/common" "github.com/aws/amazon-cloudwatch-agent/translator/util" + "github.com/aws/amazon-cloudwatch-agent/translator/util/eksdetector" ) const ( @@ -81,25 +81,32 @@ func TestGenericAppSignalsConfig(t *testing.T) { checkTranslation(t, "base_appsignals_config", "windows", expectedEnvVars, "") } -func TestAppSignalsAndKubernetesConfig(t *testing.T) { +func TestAppSignalsAndEKSConfig(t *testing.T) { resetContext(t) context.CurrentContext().SetRunInContainer(true) - context.CurrentContext().SetMode(config.ModeEC2) t.Setenv(config.HOST_NAME, "host_name_from_env") t.Setenv(config.HOST_IP, "127.0.0.1") t.Setenv(common.KubernetesEnvVar, "use_appsignals_eks_config") - common.NewDetector = common.TestEKSDetector - common.IsEKS = common.TestIsEKSCacheEKS + eksdetector.NewDetector = eksdetector.TestEKSDetector + context.CurrentContext().SetMode(config.ModeEC2) + context.CurrentContext().SetKubernetesMode(config.ModeEKS) expectedEnvVars := map[string]string{} checkTranslation(t, "appsignals_and_eks_config", "linux", expectedEnvVars, "") checkTranslation(t, "appsignals_and_eks_config", "windows", expectedEnvVars, "") +} - common.NewDetector = func() (common.Detector, error) { - return &common.EksDetector{Clientset: fake.NewSimpleClientset()}, nil - } - common.IsEKS = common.TestIsEKSCacheK8s +func TestAppSignalsAndNativeKubernetesConfig(t *testing.T) { + resetContext(t) + context.CurrentContext().SetRunInContainer(true) + t.Setenv(config.HOST_NAME, "host_name_from_env") + t.Setenv(config.HOST_IP, "127.0.0.1") + t.Setenv(common.KubernetesEnvVar, "use_appsignals_k8s_config") + eksdetector.IsEKS = eksdetector.TestIsEKSCacheK8s + context.CurrentContext().SetMode(config.ModeEC2) + context.CurrentContext().SetKubernetesMode(config.ModeK8sEC2) + expectedEnvVars := map[string]string{} checkTranslation(t, "appsignals_and_k8s_config", "linux", expectedEnvVars, "") checkTranslation(t, "appsignals_and_k8s_config", "windows", expectedEnvVars, "") } diff --git a/translator/translate/otel/exporter/awsemf/translator.go b/translator/translate/otel/exporter/awsemf/translator.go index bafd70cbef..15e16bdc12 100644 --- a/translator/translate/otel/exporter/awsemf/translator.go +++ b/translator/translate/otel/exporter/awsemf/translator.go @@ -141,15 +141,14 @@ func (t *translator) Translate(c *confmap.Conf) (component.Config, error) { } func getAppSignalsConfig() string { - if common.IsAppSignalsKubernetes() { - isEks := common.IsEKS() - if isEks.Value { - return appSignalsConfigEks - } - return appSignalsConfigK8s - } ctx := context.CurrentContext() - if ctx.Mode() == config.ModeEC2 { + kubernetesMode := ctx.KubernetesMode() + + if kubernetesMode == config.ModeEKS { + return appSignalsConfigEks + } else if kubernetesMode == config.ModeK8sEC2 || kubernetesMode == config.ModeK8sOnPrem { + return appSignalsConfigK8s + } else if ctx.Mode() == config.ModeEC2 { return appSignalsConfigEC2 } return appSignalsConfigGeneric diff --git a/translator/translate/otel/exporter/awsemf/translator_test.go b/translator/translate/otel/exporter/awsemf/translator_test.go index d32babc147..e7ca844efc 100644 --- a/translator/translate/otel/exporter/awsemf/translator_test.go +++ b/translator/translate/otel/exporter/awsemf/translator_test.go @@ -717,10 +717,8 @@ func TestTranslateAppSignals(t *testing.T) { input map[string]any want *confmap.Conf wantErr error - isKubernetes bool - isEC2 bool - detector func() (common.Detector, error) - isEKSDataStore func() common.IsEKSCache + kubernetesMode string + mode string }{ "WithAppSignalsEnabledEKS": { input: map[string]any{ @@ -730,14 +728,13 @@ func TestTranslateAppSignals(t *testing.T) { }, }}, want: testutil.GetConfWithOverrides(t, filepath.Join("appsignals_config_eks.yaml"), map[string]any{ - "local_mode": "true", + "local_mode": "false", "region": "us-east-1", "role_arn": "global_arn", "certificate_file_path": "/ca/bundle", }), - isKubernetes: true, - detector: common.TestEKSDetector, - isEKSDataStore: common.TestIsEKSCacheEKS, + kubernetesMode: config.ModeEKS, + mode: config.ModeEC2, }, "WithAppSignalsEnabledK8s": { input: map[string]any{ @@ -752,9 +749,8 @@ func TestTranslateAppSignals(t *testing.T) { "role_arn": "global_arn", "certificate_file_path": "/ca/bundle", }), - isKubernetes: true, - detector: common.TestK8sDetector, - isEKSDataStore: common.TestIsEKSCacheK8s, + kubernetesMode: config.ModeK8sOnPrem, + mode: config.ModeOnPrem, }, "WithAppSignalsEnabledGeneric": { input: map[string]any{ @@ -769,8 +765,8 @@ func TestTranslateAppSignals(t *testing.T) { "role_arn": "global_arn", "certificate_file_path": "/ca/bundle", }), - isKubernetes: false, - isEC2: false, + kubernetesMode: "", + mode: config.ModeOnPrem, }, "WithAppSignalsEnabledEC2": { input: map[string]any{ @@ -785,24 +781,15 @@ func TestTranslateAppSignals(t *testing.T) { "role_arn": "global_arn", "certificate_file_path": "/ca/bundle", }), - isEC2: true, + kubernetesMode: "", + mode: config.ModeEC2, }, } factory := awsemfexporter.NewFactory() for name, testCase := range testCases { t.Run(name, func(t *testing.T) { - if testCase.isKubernetes { - t.Setenv(common.KubernetesEnvVar, "TEST") - } - if testCase.isEC2 { - ctx := context.CurrentContext() - ctx.SetMode(config.ModeEC2) - } else { - ctx := context.CurrentContext() - ctx.SetMode(config.ModeOnPrem) - } - common.NewDetector = testCase.detector - common.IsEKS = testCase.isEKSDataStore + context.CurrentContext().SetKubernetesMode(testCase.kubernetesMode) + context.CurrentContext().SetMode(testCase.mode) conf := confmap.NewFromStringMap(testCase.input) got, err := tt.Translate(conf) assert.Equal(t, testCase.wantErr, err) diff --git a/translator/translate/otel/exporter/awsxray/translator.go b/translator/translate/otel/exporter/awsxray/translator.go index cdc6f7d0a5..1381f5cfd6 100644 --- a/translator/translate/otel/exporter/awsxray/translator.go +++ b/translator/translate/otel/exporter/awsxray/translator.go @@ -80,20 +80,15 @@ func (t *translator) Translate(conf *confmap.Conf) (component.Config, error) { cfg := t.factory.CreateDefaultConfig().(*awsxrayexporter.Config) if isAppSignals(conf) { - if common.IsAppSignalsKubernetes() { - isEks := common.IsEKS() - if isEks.Value { - cfg.IndexedAttributes = indexedAttributesEKS - } else { - cfg.IndexedAttributes = indexedAttributesK8s - } + ctx := context.CurrentContext() + if ctx.KubernetesMode() == config.ModeEKS { + cfg.IndexedAttributes = indexedAttributesEKS + } else if ctx.KubernetesMode() == config.ModeK8sEC2 || ctx.KubernetesMode() == config.ModeK8sOnPrem { + cfg.IndexedAttributes = indexedAttributesK8s + } else if ctx.Mode() == config.ModeEC2 { + cfg.IndexedAttributes = indexedAttributesEC2 } else { - ctx := context.CurrentContext() - if ctx.Mode() == config.ModeEC2 { - cfg.IndexedAttributes = indexedAttributesEC2 - } else { - cfg.IndexedAttributes = indexedAttributesGeneric - } + cfg.IndexedAttributes = indexedAttributesGeneric } } diff --git a/translator/translate/otel/exporter/awsxray/translator_test.go b/translator/translate/otel/exporter/awsxray/translator_test.go index cf6f54dab7..44fab012db 100644 --- a/translator/translate/otel/exporter/awsxray/translator_test.go +++ b/translator/translate/otel/exporter/awsxray/translator_test.go @@ -31,10 +31,8 @@ func TestTranslator(t *testing.T) { input map[string]any want *confmap.Conf wantErr error - detector func() (common.Detector, error) - isEKSDataStore func() common.IsEKSCache - isKubernetes bool - isEC2 bool + kubernetesMode string + mode string }{ "WithMissingKey": { input: map[string]any{"logs": map[string]any{}}, @@ -42,12 +40,14 @@ func TestTranslator(t *testing.T) { ID: tt.ID(), JsonKey: common.TracesKey, }, + mode: config.ModeOnPrem, }, "WithDefault": { input: map[string]any{"traces": map[string]any{}}, want: confmap.NewFromStringMap(map[string]any{ "certificate_file_path": "/ca/bundle", "region": "us-east-1", + "local_mode": "true", "role_arn": "global_arn", "imds_retries": 1, "telemetry": map[string]any{ @@ -56,10 +56,12 @@ func TestTranslator(t *testing.T) { }, "middleware": "agenthealth/traces", }), + mode: config.ModeOnPrem, }, "WithCompleteConfig": { input: testutil.GetJson(t, filepath.Join("testdata", "config.json")), want: testutil.GetConf(t, filepath.Join("testdata", "config.yaml")), + mode: config.ModeOnPrem, }, "WithAppSignalsEnabledEKS": { input: map[string]any{ @@ -90,9 +92,8 @@ func TestTranslator(t *testing.T) { }, "middleware": "agenthealth/traces", }), - detector: common.TestEKSDetector, - isEKSDataStore: common.TestIsEKSCacheEKS, - isKubernetes: true, + kubernetesMode: config.ModeEKS, + mode: config.ModeEC2, }, "WithAppSignalsEnabledK8s": { input: map[string]any{ @@ -123,9 +124,8 @@ func TestTranslator(t *testing.T) { }, "middleware": "agenthealth/traces", }), - detector: common.TestK8sDetector, - isEKSDataStore: common.TestIsEKSCacheK8s, - isKubernetes: true, + kubernetesMode: config.ModeK8sEC2, + mode: config.ModeEC2, }, "WithAppSignalsEnabledEC2": { input: map[string]any{ @@ -153,21 +153,14 @@ func TestTranslator(t *testing.T) { }, "middleware": "agenthealth/traces", }), - isEC2: true, + mode: config.ModeEC2, }, } factory := awsxrayexporter.NewFactory() for name, testCase := range testCases { t.Run(name, func(t *testing.T) { - if testCase.isKubernetes { - t.Setenv(common.KubernetesEnvVar, "TEST") - common.NewDetector = testCase.detector - common.IsEKS = testCase.isEKSDataStore - } - if testCase.isEC2 { - ctx := context.CurrentContext() - ctx.SetMode(config.ModeEC2) - } + context.CurrentContext().SetKubernetesMode(testCase.kubernetesMode) + context.CurrentContext().SetMode(testCase.mode) conf := confmap.NewFromStringMap(testCase.input) got, err := tt.Translate(conf) assert.Equal(t, testCase.wantErr, err) diff --git a/translator/translate/otel/pipeline/appsignals/translator_test.go b/translator/translate/otel/pipeline/appsignals/translator_test.go index 4bf4a4c0ca..a60c376d04 100644 --- a/translator/translate/otel/pipeline/appsignals/translator_test.go +++ b/translator/translate/otel/pipeline/appsignals/translator_test.go @@ -16,6 +16,7 @@ import ( "github.com/aws/amazon-cloudwatch-agent/translator/config" "github.com/aws/amazon-cloudwatch-agent/translator/context" "github.com/aws/amazon-cloudwatch-agent/translator/translate/otel/common" + "github.com/aws/amazon-cloudwatch-agent/translator/util/eksdetector" ) func TestTranslatorTraces(t *testing.T) { @@ -31,8 +32,8 @@ func TestTranslatorTraces(t *testing.T) { input map[string]interface{} want *want wantErr error - detector func() (common.Detector, error) - isEKSCache func() common.IsEKSCache + detector func() (eksdetector.Detector, error) + isEKSCache func() eksdetector.IsEKSCache }{ "WithoutTracesCollectedKey": { input: map[string]interface{}{}, @@ -52,8 +53,8 @@ func TestTranslatorTraces(t *testing.T) { exporters: []string{"awsxray/app_signals"}, extensions: []string{"awsproxy/app_signals", "agenthealth/traces"}, }, - detector: common.TestEKSDetector, - isEKSCache: common.TestIsEKSCacheEKS, + detector: eksdetector.TestEKSDetector, + isEKSCache: eksdetector.TestIsEKSCacheEKS, }, "WithAppSignalsEnabledK8s": { input: map[string]interface{}{ @@ -69,15 +70,15 @@ func TestTranslatorTraces(t *testing.T) { exporters: []string{"awsxray/app_signals"}, extensions: []string{"awsproxy/app_signals", "agenthealth/traces"}, }, - detector: common.TestK8sDetector, - isEKSCache: common.TestIsEKSCacheK8s, + detector: eksdetector.TestK8sDetector, + isEKSCache: eksdetector.TestIsEKSCacheK8s, }, } for name, testCase := range testCases { t.Run(name, func(t *testing.T) { t.Setenv(common.KubernetesEnvVar, "TEST") - common.NewDetector = testCase.detector - common.IsEKS = testCase.isEKSCache + eksdetector.NewDetector = testCase.detector + eksdetector.IsEKS = testCase.isEKSCache conf := confmap.NewFromStringMap(testCase.input) got, err := tt.Translate(conf) assert.Equal(t, testCase.wantErr, err) @@ -107,8 +108,8 @@ func TestTranslatorMetricsForKubernetes(t *testing.T) { input map[string]interface{} want *want wantErr error - detector func() (common.Detector, error) - isEKSCache func() common.IsEKSCache + detector func() (eksdetector.Detector, error) + isEKSCache func() eksdetector.IsEKSCache }{ "WithoutMetricsCollectedKey": { input: map[string]interface{}{}, @@ -128,8 +129,8 @@ func TestTranslatorMetricsForKubernetes(t *testing.T) { exporters: []string{"awsemf/app_signals"}, extensions: []string{"agenthealth/logs"}, }, - detector: common.TestEKSDetector, - isEKSCache: common.TestIsEKSCacheEKS, + detector: eksdetector.TestEKSDetector, + isEKSCache: eksdetector.TestIsEKSCacheEKS, }, "WithAppSignalsEnabledK8s": { input: map[string]interface{}{ @@ -145,15 +146,15 @@ func TestTranslatorMetricsForKubernetes(t *testing.T) { exporters: []string{"awsemf/app_signals"}, extensions: []string{"agenthealth/logs"}, }, - detector: common.TestK8sDetector, - isEKSCache: common.TestIsEKSCacheK8s, + detector: eksdetector.TestK8sDetector, + isEKSCache: eksdetector.TestIsEKSCacheK8s, }, } for name, testCase := range testCases { t.Run(name, func(t *testing.T) { t.Setenv(common.KubernetesEnvVar, "TEST") - common.NewDetector = testCase.detector - common.IsEKS = testCase.isEKSCache + eksdetector.NewDetector = testCase.detector + eksdetector.IsEKS = testCase.isEKSCache conf := confmap.NewFromStringMap(testCase.input) got, err := tt.Translate(conf) assert.Equal(t, testCase.wantErr, err) @@ -182,8 +183,8 @@ func TestTranslatorMetricsForEC2(t *testing.T) { input map[string]interface{} want *want wantErr error - detector func() (common.Detector, error) - isEKSCache func() common.IsEKSCache + detector func() (eksdetector.Detector, error) + isEKSCache func() eksdetector.IsEKSCache }{ "WithoutMetricsCollectedKey": { input: map[string]interface{}{}, @@ -203,8 +204,8 @@ func TestTranslatorMetricsForEC2(t *testing.T) { exporters: []string{"awsemf/app_signals"}, extensions: []string{"agenthealth/logs"}, }, - detector: common.TestEKSDetector, - isEKSCache: common.TestIsEKSCacheEKS, + detector: eksdetector.TestEKSDetector, + isEKSCache: eksdetector.TestIsEKSCacheEKS, }, } for name, testCase := range testCases { diff --git a/translator/translate/otel/processor/awsappsignals/translator.go b/translator/translate/otel/processor/awsappsignals/translator.go index f8e778138b..7ec8100391 100644 --- a/translator/translate/otel/processor/awsappsignals/translator.go +++ b/translator/translate/otel/processor/awsappsignals/translator.go @@ -69,25 +69,27 @@ func (t *translator) Translate(conf *confmap.Conf) (component.Config, error) { if !hostedInConfigured { hostedIn = util.GetClusterNameFromEc2Tagger() } + } - isEks := common.IsEKS() - if isEks.Value { - cfg.Resolvers = []appsignalsconfig.Resolver{ - appsignalsconfig.NewEKSResolver(hostedIn), - } - } else { - cfg.Resolvers = []appsignalsconfig.Resolver{ - appsignalsconfig.NewK8sResolver(hostedIn), - } + kubernetesMode := context.CurrentContext().KubernetesMode() + switch kubernetesMode { + case config.ModeEKS: + cfg.Resolvers = []appsignalsconfig.Resolver{ + appsignalsconfig.NewEKSResolver(hostedIn), + } + case config.ModeK8sEC2, config.ModeK8sOnPrem: + cfg.Resolvers = []appsignalsconfig.Resolver{ + appsignalsconfig.NewK8sResolver(hostedIn), } - } else { - // Non-kubernetes environment detected. - ctx := context.CurrentContext() - if ctx.Mode() == config.ModeEC2 { + } + + if kubernetesMode == "" { + switch context.CurrentContext().Mode() { + case config.ModeEC2: cfg.Resolvers = []appsignalsconfig.Resolver{ appsignalsconfig.NewEC2Resolver(hostedIn), } - } else { + default: cfg.Resolvers = []appsignalsconfig.Resolver{ appsignalsconfig.NewGenericResolver(hostedIn), } diff --git a/translator/translate/otel/processor/awsappsignals/translator_test.go b/translator/translate/otel/processor/awsappsignals/translator_test.go index 07a07c198d..b15922aff4 100644 --- a/translator/translate/otel/processor/awsappsignals/translator_test.go +++ b/translator/translate/otel/processor/awsappsignals/translator_test.go @@ -51,9 +51,8 @@ func TestTranslate(t *testing.T) { want string wantErr error isKubernetes bool - isEC2 bool - detector func() (common.Detector, error) - isEKSDataStore func() common.IsEKSCache + kubernetesMode string + mode string }{ //The config for the awsappsignals processor is https://code.amazon.com/packages/AWSTracingSamplePetClinic/blobs/97ce3c409986ac8ae014de1e3fe71fdb98080f22/--/eks/appsignals/auto-instrumentation-new.yaml#L20 //The awsappsignals processor config does not have a platform field, instead it gets added to resolvers when marshalled @@ -68,15 +67,15 @@ func TestTranslate(t *testing.T) { }}, want: validAppSignalsYamlEKS, isKubernetes: true, - detector: common.TestEKSDetector, - isEKSDataStore: common.TestIsEKSCacheEKS, + kubernetesMode: translatorConfig.ModeEKS, + mode: translatorConfig.ModeEC2, }, "WithAppSignalsCustomRulesEnabledEKS": { input: validJsonMap, want: validAppSignalsRulesYamlEKS, isKubernetes: true, - detector: common.TestEKSDetector, - isEKSDataStore: common.TestIsEKSCacheEKS, + kubernetesMode: translatorConfig.ModeEKS, + mode: translatorConfig.ModeEC2, }, "WithAppSignalsEnabledK8S": { input: map[string]interface{}{ @@ -89,8 +88,8 @@ func TestTranslate(t *testing.T) { }}, want: validAppSignalsYamlK8s, isKubernetes: true, - detector: common.TestK8sDetector, - isEKSDataStore: common.TestIsEKSCacheK8s, + kubernetesMode: translatorConfig.ModeK8sEC2, + mode: translatorConfig.ModeEC2, }, "WithAppSignalsEnabledGeneric": { input: map[string]interface{}{ @@ -101,16 +100,18 @@ func TestTranslate(t *testing.T) { }}, want: validAppSignalsYamlGeneric, isKubernetes: false, - isEC2: false, + mode: translatorConfig.ModeOnPrem, }, "WithAppSignalsCustomRulesEnabledGeneric": { input: validJsonMap, want: validAppSignalsRulesYamlGeneric, isKubernetes: false, + mode: translatorConfig.ModeOnPrem, }, "WithInvalidAppSignalsCustomRulesEnabled": { input: invalidJsonMap, wantErr: errors.New("replace action set, but no replacements defined for service rule"), + mode: translatorConfig.ModeOnPrem, }, "WithAppSignalsEnabledEC2": { input: map[string]interface{}{ @@ -121,8 +122,8 @@ func TestTranslate(t *testing.T) { }, }, }}, - want: validAppSignalsYamlEC2, - isEC2: true, + want: validAppSignalsYamlEC2, + mode: translatorConfig.ModeEC2, }, } factory := awsappsignals.NewFactory() @@ -131,14 +132,8 @@ func TestTranslate(t *testing.T) { if testCase.isKubernetes { t.Setenv(common.KubernetesEnvVar, "TEST") } - ctx := context.CurrentContext() - if testCase.isEC2 { - ctx.SetMode(translatorConfig.ModeEC2) - } else { - ctx.SetMode(translatorConfig.ModeOnPrem) - } - common.NewDetector = testCase.detector - common.IsEKS = testCase.isEKSDataStore + context.CurrentContext().SetKubernetesMode(testCase.kubernetesMode) + context.CurrentContext().SetMode(testCase.mode) conf := confmap.NewFromStringMap(testCase.input) got, err := tt.Translate(conf) assert.Equal(t, testCase.wantErr, err) diff --git a/translator/translate/otel/translate_otel_test.go b/translator/translate/otel/translate_otel_test.go index f3759b437c..8df2340bf6 100644 --- a/translator/translate/otel/translate_otel_test.go +++ b/translator/translate/otel/translate_otel_test.go @@ -15,6 +15,7 @@ import ( _ "github.com/aws/amazon-cloudwatch-agent/translator/registerrules" "github.com/aws/amazon-cloudwatch-agent/translator/translate/agent" "github.com/aws/amazon-cloudwatch-agent/translator/translate/otel/common" + "github.com/aws/amazon-cloudwatch-agent/translator/util/eksdetector" ) func TestTranslator(t *testing.T) { @@ -22,8 +23,8 @@ func TestTranslator(t *testing.T) { testCases := map[string]struct { input interface{} wantErrContains string - detector func() (common.Detector, error) - isEKSDataStore func() common.IsEKSCache + detector func() (eksdetector.Detector, error) + isEKSDataStore func() eksdetector.IsEKSCache }{ "WithInvalidConfig": { input: "", @@ -56,8 +57,8 @@ func TestTranslator(t *testing.T) { }, }, }, - detector: common.TestEKSDetector, - isEKSDataStore: common.TestIsEKSCacheEKS, + detector: eksdetector.TestEKSDetector, + isEKSDataStore: eksdetector.TestIsEKSCacheEKS, }, "WithAppSignalsTracesEnabled": { input: map[string]interface{}{ @@ -67,8 +68,8 @@ func TestTranslator(t *testing.T) { }, }, }, - detector: common.TestEKSDetector, - isEKSDataStore: common.TestIsEKSCacheEKS, + detector: eksdetector.TestEKSDetector, + isEKSDataStore: eksdetector.TestIsEKSCacheEKS, }, "WithAppSignalsMetricsAndTracesEnabled": { input: map[string]interface{}{ @@ -83,8 +84,8 @@ func TestTranslator(t *testing.T) { }, }, }, - detector: common.TestEKSDetector, - isEKSDataStore: common.TestIsEKSCacheEKS, + detector: eksdetector.TestEKSDetector, + isEKSDataStore: eksdetector.TestIsEKSCacheEKS, }, "WithAppSignalsMultipleMetricsReceiversConfig": { input: map[string]interface{}{ @@ -102,14 +103,14 @@ func TestTranslator(t *testing.T) { }, }, }, - detector: common.TestEKSDetector, - isEKSDataStore: common.TestIsEKSCacheEKS, + detector: eksdetector.TestEKSDetector, + isEKSDataStore: eksdetector.TestIsEKSCacheEKS, }, } for name, testCase := range testCases { t.Run(name, func(t *testing.T) { - common.NewDetector = testCase.detector - common.IsEKS = testCase.isEKSDataStore + eksdetector.NewDetector = testCase.detector + eksdetector.IsEKS = testCase.isEKSDataStore translator.SetTargetPlatform("linux") got, err := Translate(testCase.input, "linux") if testCase.wantErrContains != "" { diff --git a/translator/translate/otel/common/eksdetector.go b/translator/util/eksdetector/eksdetector.go similarity index 99% rename from translator/translate/otel/common/eksdetector.go rename to translator/util/eksdetector/eksdetector.go index 6e6a926860..58830883d6 100644 --- a/translator/translate/otel/common/eksdetector.go +++ b/translator/util/eksdetector/eksdetector.go @@ -1,7 +1,7 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: MIT -package common +package eksdetector import ( "context" diff --git a/translator/translate/otel/common/eksdetector_test.go b/translator/util/eksdetector/eksdetector_test.go similarity index 99% rename from translator/translate/otel/common/eksdetector_test.go rename to translator/util/eksdetector/eksdetector_test.go index 0f7f64478e..a5dafaf446 100644 --- a/translator/translate/otel/common/eksdetector_test.go +++ b/translator/util/eksdetector/eksdetector_test.go @@ -1,7 +1,7 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: MIT -package common +package eksdetector import ( "fmt" diff --git a/translator/translate/otel/common/eksdetectortestutil.go b/translator/util/eksdetector/eksdetectortestutil.go similarity index 98% rename from translator/translate/otel/common/eksdetectortestutil.go rename to translator/util/eksdetector/eksdetectortestutil.go index fa108a341e..c3b14a48c5 100644 --- a/translator/translate/otel/common/eksdetectortestutil.go +++ b/translator/util/eksdetector/eksdetectortestutil.go @@ -1,7 +1,7 @@ // Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved. // SPDX-License-Identifier: MIT -package common +package eksdetector import ( "github.com/stretchr/testify/mock" diff --git a/translator/util/sdkutil.go b/translator/util/sdkutil.go index c17fdec5cc..d0bb20510b 100644 --- a/translator/util/sdkutil.go +++ b/translator/util/sdkutil.go @@ -17,6 +17,7 @@ import ( "github.com/aws/amazon-cloudwatch-agent/translator/config" "github.com/aws/amazon-cloudwatch-agent/translator/util/ec2util" "github.com/aws/amazon-cloudwatch-agent/translator/util/ecsutil" + "github.com/aws/amazon-cloudwatch-agent/translator/util/eksdetector" ) const ( @@ -27,6 +28,7 @@ var DetectRegion = detectRegion var DetectCredentialsPath = detectCredentialsPath var DefaultEC2Region = defaultEC2Region var DefaultECSRegion = defaultECSRegion +var IsEKS = isEKS var runInAws = os.Getenv(config.RUN_IN_AWS) var runWithIrsa = os.Getenv(config.RUN_WITH_IRSA) @@ -59,6 +61,25 @@ func DetectAgentMode(configuredMode string) string { return config.ModeOnPrem } +func DetectKubernetesMode(configuredMode string) string { + isEKS := IsEKS() + + if isEKS.Err != nil { + return "" // not kubernetes + } + + if isEKS.Value { + return config.ModeEKS + } + + if configuredMode == config.ModeEC2 { + return config.ModeK8sEC2 + } + + return config.ModeK8sOnPrem + +} + func SDKRegionWithCredsMap(mode string, credsConfig map[string]string) (region string) { credsMap := GetCredentials(mode, credsConfig) @@ -97,6 +118,10 @@ func defaultECSRegion() string { return ecsutil.GetECSUtilSingleton().Region } +func isEKS() eksdetector.IsEKSCache { + return eksdetector.IsEKS() +} + func detectRegion(mode string, credsConfig map[string]string) (region string, regionType string) { region = SDKRegionWithCredsMap(mode, credsConfig) regionType = config.RegionTypeNotFound @@ -106,6 +131,7 @@ func detectRegion(mode string, credsConfig map[string]string) (region string, re // For ec2, fallback to metadata when no region info found in credential profile. if region == "" && mode == config.ModeEC2 { + fmt.Println("I! Trying to detect region from ec2") region = DefaultEC2Region() regionType = config.RegionTypeEC2Metadata diff --git a/translator/util/sdkutil_test.go b/translator/util/sdkutil_test.go index eb6bdeec25..94d4d4f3c6 100644 --- a/translator/util/sdkutil_test.go +++ b/translator/util/sdkutil_test.go @@ -4,11 +4,13 @@ package util import ( + "fmt" "testing" "github.com/stretchr/testify/require" "github.com/aws/amazon-cloudwatch-agent/translator/config" + "github.com/aws/amazon-cloudwatch-agent/translator/util/eksdetector" ) func TestDetectAgentModeAuto(t *testing.T) { @@ -32,3 +34,25 @@ func TestDetectAgentModeAuto(t *testing.T) { }) } } + +func TestDetectKubernetesMode(t *testing.T) { + testCases := map[string]struct { + isEKS bool + isEKSErr error + configuredMode string + wantKubernetesMode string + }{ + "EKS": {isEKS: true, isEKSErr: nil, configuredMode: config.ModeEC2, wantKubernetesMode: config.ModeEKS}, + "K8sEC2": {isEKS: false, isEKSErr: nil, configuredMode: config.ModeEC2, wantKubernetesMode: config.ModeK8sEC2}, + "K8sOnPrem": {isEKS: false, isEKSErr: nil, configuredMode: config.ModeOnPrem, wantKubernetesMode: config.ModeK8sOnPrem}, + "NotKubernetes": {isEKS: false, isEKSErr: fmt.Errorf("error"), configuredMode: config.ModeEC2, wantKubernetesMode: ""}, + } + for name, testCase := range testCases { + t.Run(name, func(t *testing.T) { + IsEKS = func() eksdetector.IsEKSCache { + return eksdetector.IsEKSCache{Value: testCase.isEKS, Err: testCase.isEKSErr} + } + require.Equal(t, testCase.wantKubernetesMode, DetectKubernetesMode(testCase.configuredMode)) + }) + } +}