From 1a276996bc1d33b578d60b757bca8eed6f6328a0 Mon Sep 17 00:00:00 2001 From: LZiHaN Date: Thu, 12 Dec 2024 17:23:13 +0800 Subject: [PATCH] Migrating datadog exporter to use aws sdk v2 --- exporter/datadogexporter/go.mod | 16 +- exporter/datadogexporter/go.sum | 28 +++ .../internal/hostmetadata/internal/ec2/ec2.go | 70 +++--- .../hostmetadata/internal/ec2/ec2_test.go | 10 +- .../metadataproviders/aws/ec2/metadata.go | 42 +++- .../aws/ec2/metadata_test.go | 208 ++++++++++++++---- internal/metadataproviders/go.mod | 5 +- internal/metadataproviders/go.sum | 12 +- processor/resourcedetectionprocessor/go.mod | 14 ++ processor/resourcedetectionprocessor/go.sum | 28 +++ .../internal/aws/ec2/ec2.go | 44 ++-- .../internal/aws/ec2/ec2_test.go | 69 +++--- 12 files changed, 401 insertions(+), 145 deletions(-) diff --git a/exporter/datadogexporter/go.mod b/exporter/datadogexporter/go.mod index 31f3da971be1..4dbbbaa4856e 100644 --- a/exporter/datadogexporter/go.mod +++ b/exporter/datadogexporter/go.mod @@ -38,7 +38,7 @@ require ( github.com/DataDog/opentelemetry-mapping-go/pkg/quantile v0.21.0 github.com/DataDog/sketches-go v1.4.6 // indirect github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.25.0 - github.com/aws/aws-sdk-go v1.55.5 + github.com/aws/aws-sdk-go v1.55.5 // indirect github.com/cenkalti/backoff/v4 v4.3.0 github.com/google/go-cmp v0.6.0 github.com/open-telemetry/opentelemetry-collector-contrib/connector/datadogconnector v0.115.0 @@ -91,6 +91,10 @@ require ( ) require ( + github.com/aws/aws-sdk-go-v2 v1.32.6 + github.com/aws/aws-sdk-go-v2/config v1.28.6 + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.21 + github.com/aws/aws-sdk-go-v2/service/ec2 v1.196.0 github.com/open-telemetry/opentelemetry-collector-contrib/pkg/datadog v0.115.0 go.opentelemetry.io/collector/component/componenttest v0.115.1-0.20241206185113-3f3e208e71b8 go.opentelemetry.io/collector/consumer/consumererror v0.115.1-0.20241206185113-3f3e208e71b8 @@ -158,6 +162,16 @@ require ( github.com/antchfx/xmlquery v1.4.2 // indirect github.com/antchfx/xpath v1.3.2 // indirect github.com/armon/go-metrics v0.4.1 // indirect + github.com/aws/aws-sdk-go-v2/credentials v1.17.47 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.25 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.25 // indirect + github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.1 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.6 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.24.7 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.6 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.33.2 // indirect + github.com/aws/smithy-go v1.22.1 // indirect github.com/benbjohnson/clock v1.3.5 // indirect github.com/beorn7/perks v1.0.1 // indirect github.com/bmatcuk/doublestar/v4 v4.7.1 // indirect diff --git a/exporter/datadogexporter/go.sum b/exporter/datadogexporter/go.sum index 441c1c948677..d5bf39d45828 100644 --- a/exporter/datadogexporter/go.sum +++ b/exporter/datadogexporter/go.sum @@ -279,6 +279,34 @@ github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:l github.com/aws/aws-sdk-go v1.38.35/go.mod h1:hcU610XS61/+aQV88ixoOzUoG7v3b31pl2zKMmprdro= github.com/aws/aws-sdk-go v1.55.5 h1:KKUZBfBoyqy5d3swXyiC7Q76ic40rYcbqH7qjh59kzU= github.com/aws/aws-sdk-go v1.55.5/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU= +github.com/aws/aws-sdk-go-v2 v1.32.6 h1:7BokKRgRPuGmKkFMhEg/jSul+tB9VvXhcViILtfG8b4= +github.com/aws/aws-sdk-go-v2 v1.32.6/go.mod h1:P5WJBrYqqbWVaOxgH0X/FYYD47/nooaPOZPlQdmiN2U= +github.com/aws/aws-sdk-go-v2/config v1.28.6 h1:D89IKtGrs/I3QXOLNTH93NJYtDhm8SYa9Q5CsPShmyo= +github.com/aws/aws-sdk-go-v2/config v1.28.6/go.mod h1:GDzxJ5wyyFSCoLkS+UhGB0dArhb9mI+Co4dHtoTxbko= +github.com/aws/aws-sdk-go-v2/credentials v1.17.47 h1:48bA+3/fCdi2yAwVt+3COvmatZ6jUDNkDTIsqDiMUdw= +github.com/aws/aws-sdk-go-v2/credentials v1.17.47/go.mod h1:+KdckOejLW3Ks3b0E3b5rHsr2f9yuORBum0WPnE5o5w= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.21 h1:AmoU1pziydclFT/xRV+xXE/Vb8fttJCLRPv8oAkprc0= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.21/go.mod h1:AjUdLYe4Tgs6kpH4Bv7uMZo7pottoyHMn4eTcIcneaY= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.25 h1:s/fF4+yDQDoElYhfIVvSNyeCydfbuTKzhxSXDXCPasU= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.25/go.mod h1:IgPfDv5jqFIzQSNbUEMoitNooSMXjRSDkhXv8jiROvU= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.25 h1:ZntTCl5EsYnhN/IygQEUugpdwbhdkom9uHcbCftiGgA= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.25/go.mod h1:DBdPrgeocww+CSl1C8cEV8PN1mHMBhuCDLpXezyvWkE= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 h1:VaRN3TlFdd6KxX1x3ILT5ynH6HvKgqdiXoTxAF4HQcQ= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1/go.mod h1:FbtygfRFze9usAadmnGJNc8KsP346kEe+y2/oyhGAGc= +github.com/aws/aws-sdk-go-v2/service/ec2 v1.196.0 h1:ZBtoihAqfT+5b1FwGHOubq8k10KwaIyKZd2/CRTucAU= +github.com/aws/aws-sdk-go-v2/service/ec2 v1.196.0/go.mod h1:00zqVNJFK6UASrTnuvjJHJuaqUdkVz5tW8Ip+VhzuNg= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.1 h1:iXtILhvDxB6kPvEXgsDhGaZCSC6LQET5ZHSdJozeI0Y= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.1/go.mod h1:9nu0fVANtYiAePIBh2/pFUSwtJ402hLnp854CNoDOeE= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.6 h1:50+XsN70RS7dwJ2CkVNXzj7U2L1HKP8nqTd3XWEXBN4= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.6/go.mod h1:WqgLmwY7so32kG01zD8CPTJWVWM+TzJoOVHwTg4aPug= +github.com/aws/aws-sdk-go-v2/service/sso v1.24.7 h1:rLnYAfXQ3YAccocshIH5mzNNwZBkBo+bP6EhIxak6Hw= +github.com/aws/aws-sdk-go-v2/service/sso v1.24.7/go.mod h1:ZHtuQJ6t9A/+YDuxOLnbryAmITtr8UysSny3qcyvJTc= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.6 h1:JnhTZR3PiYDNKlXy50/pNeix9aGMo6lLpXwJ1mw8MD4= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.6/go.mod h1:URronUEGfXZN1VpdktPSD1EkAL9mfrV+2F4sjH38qOY= +github.com/aws/aws-sdk-go-v2/service/sts v1.33.2 h1:s4074ZO1Hk8qv65GqNXqDjmkf4HSQqJukaLuuW0TpDA= +github.com/aws/aws-sdk-go-v2/service/sts v1.33.2/go.mod h1:mVggCnIWoM09jP71Wh+ea7+5gAp53q+49wDFs1SW5z8= +github.com/aws/smithy-go v1.22.1 h1:/HPHZQ0g7f4eUeK6HKglFz8uwVfZKgoI25rb/J+dnro= +github.com/aws/smithy-go v1.22.1/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg= github.com/bboreham/go-loser v0.0.0-20230920113527-fcc2c21820a3 h1:6df1vn4bBlDDo4tARvBm7l6KA9iVMnE3NWizDeWSrps= github.com/bboreham/go-loser v0.0.0-20230920113527-fcc2c21820a3/go.mod h1:CIWtjkly68+yqLPbvwwR/fjNJA/idrtULjZWh2v1ys0= github.com/benbjohnson/clock v1.3.5 h1:VvXlSJBzZpA/zum6Sj74hxwYI2DIxRWuNIoXAzHZz5o= diff --git a/exporter/datadogexporter/internal/hostmetadata/internal/ec2/ec2.go b/exporter/datadogexporter/internal/hostmetadata/internal/ec2/ec2.go index ef20a5382106..f72ef502ab4d 100644 --- a/exporter/datadogexporter/internal/hostmetadata/internal/ec2/ec2.go +++ b/exporter/datadogexporter/internal/hostmetadata/internal/ec2/ec2.go @@ -7,14 +7,18 @@ package ec2 // import "github.com/open-telemetry/opentelemetry-collector-contrib import ( "context" "fmt" + "io" "strings" "sync" + "github.com/aws/aws-sdk-go-v2/config" + "github.com/aws/aws-sdk-go-v2/feature/ec2/imds" + "github.com/aws/aws-sdk-go-v2/service/ec2/types" + "github.com/DataDog/opentelemetry-mapping-go/pkg/otlp/attributes/source" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/ec2metadata" - "github.com/aws/aws-sdk-go/aws/session" - "github.com/aws/aws-sdk-go/service/ec2" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/service/ec2" + "go.uber.org/zap" "github.com/open-telemetry/opentelemetry-collector-contrib/exporter/datadogexporter/internal/hostmetadata/provider" @@ -42,31 +46,42 @@ func isDefaultHostname(hostname string) bool { // GetHostInfo gets the hostname info from EC2 metadata func GetHostInfo(ctx context.Context, logger *zap.Logger) (hostInfo *HostInfo) { - sess, err := session.NewSession() hostInfo = &HostInfo{} + cfg, err := config.LoadDefaultConfig(ctx) if err != nil { - logger.Warn("Failed to build AWS session", zap.Error(err)) + logger.Warn("Failed to build AWS config", zap.Error(err)) return } - meta := ec2metadata.New(sess) + client := imds.NewFromConfig(cfg) - if !meta.AvailableWithContext(ctx) { - logger.Debug("EC2 Metadata not available") + // Check if metadata service is available by trying to retrieve instance ID + _, err = client.GetMetadata(ctx, &imds.GetMetadataInput{ + Path: "instance-id", + }) + if err != nil { + logger.Debug("EC2 Metadata service is not available", zap.Error(err)) return } - if idDoc, err := meta.GetInstanceIdentityDocumentWithContext(ctx); err == nil { + if idDoc, err := client.GetInstanceIdentityDocument(ctx, &imds.GetInstanceIdentityDocumentInput{}); err == nil { hostInfo.InstanceID = idDoc.InstanceID } else { logger.Warn("Failed to get EC2 instance id document", zap.Error(err)) } - if ec2Hostname, err := meta.GetMetadataWithContext(ctx, "hostname"); err == nil { - hostInfo.EC2Hostname = ec2Hostname + metadataOutput, err := client.GetMetadata(ctx, &imds.GetMetadataInput{Path: "hostname"}) + if err != nil { + logger.Warn("Failed to retrieve EC2 hostname", zap.Error(err)) } else { - logger.Warn("Failed to get EC2 hostname", zap.Error(err)) + defer metadataOutput.Content.Close() + hostnameBytes, readErr := io.ReadAll(metadataOutput.Content) + if readErr != nil { + logger.Warn("Failed to read EC2 hostname content", zap.Error(readErr)) + } else { + hostInfo.EC2Hostname = string(hostnameBytes) + } } return @@ -94,13 +109,13 @@ type Provider struct { } func NewProvider(logger *zap.Logger) (*Provider, error) { - sess, err := session.NewSession() + cfg, err := config.LoadDefaultConfig(context.Background()) if err != nil { return nil, err } return &Provider{ logger: logger, - detector: ec2provider.NewProvider(sess), + detector: ec2provider.NewProvider(cfg), }, nil } @@ -129,23 +144,20 @@ func (p *Provider) instanceTags(ctx context.Context) (*ec2.DescribeTagsOutput, e // Similar to: // - https://github.com/open-telemetry/opentelemetry-collector-contrib/blob/39dbc1ac8/processor/resourcedetectionprocessor/internal/aws/ec2/ec2.go#L118-L151 // - https://github.com/DataDog/datadog-agent/blob/1b4afdd6a03e8fabcc169b924931b2bb8935dab9/pkg/util/ec2/ec2_tags.go#L104-L134 - sess, err := session.NewSession(&aws.Config{ - Region: aws.String(meta.Region), - }) + cfg, err := config.LoadDefaultConfig(ctx, + config.WithRegion(meta.Region), + ) if err != nil { - return nil, fmt.Errorf("failed to build AWS session: %w", err) + return nil, fmt.Errorf("failed to load AWS config: %w", err) } - svc := ec2.New(sess) - return svc.DescribeTagsWithContext(ctx, - &ec2.DescribeTagsInput{ - Filters: []*ec2.Filter{{ - Name: aws.String("resource-id"), - Values: []*string{ - aws.String(meta.InstanceID), - }, - }}, - }) + client := ec2.NewFromConfig(cfg) + return client.DescribeTags(ctx, &ec2.DescribeTagsInput{ + Filters: []types.Filter{{ + Name: aws.String("resource-id"), + Values: []string{meta.InstanceID}, + }}, + }) } // clusterNameFromTags gets the AWS EC2 Cluster name from the tags on an EC2 instance. diff --git a/exporter/datadogexporter/internal/hostmetadata/internal/ec2/ec2_test.go b/exporter/datadogexporter/internal/hostmetadata/internal/ec2/ec2_test.go index 26d697236466..5a172863d52d 100644 --- a/exporter/datadogexporter/internal/hostmetadata/internal/ec2/ec2_test.go +++ b/exporter/datadogexporter/internal/hostmetadata/internal/ec2/ec2_test.go @@ -5,7 +5,9 @@ package ec2 import ( "testing" - "github.com/aws/aws-sdk-go/service/ec2" + "github.com/aws/aws-sdk-go-v2/service/ec2" + "github.com/aws/aws-sdk-go-v2/service/ec2/types" + "github.com/stretchr/testify/assert" "go.uber.org/zap" ) @@ -56,7 +58,7 @@ func TestClusterNameFromEC2Tags(t *testing.T) { name: "missing cluster name tag", ec2Tags: &ec2.DescribeTagsOutput{ NextToken: strp("NextToken"), - Tags: []*ec2.TagDescription{ + Tags: []types.TagDescription{ {Key: strp("some key"), Value: strp("some value")}, }, }, @@ -66,7 +68,7 @@ func TestClusterNameFromEC2Tags(t *testing.T) { name: "cluster name tag only has the prefix", ec2Tags: &ec2.DescribeTagsOutput{ NextToken: strp("NextToken"), - Tags: []*ec2.TagDescription{ + Tags: []types.TagDescription{ {Key: strp("some key"), Value: strp("some value")}, {Key: strp("kubernetes.io/cluster/"), Value: strp("some value")}, }, @@ -77,7 +79,7 @@ func TestClusterNameFromEC2Tags(t *testing.T) { name: "cluster name is available", ec2Tags: &ec2.DescribeTagsOutput{ NextToken: strp("NextToken"), - Tags: []*ec2.TagDescription{ + Tags: []types.TagDescription{ {Key: strp("some key"), Value: strp("some value")}, {Key: strp("kubernetes.io/cluster/myclustername"), Value: strp("some value")}, }, diff --git a/internal/metadataproviders/aws/ec2/metadata.go b/internal/metadataproviders/aws/ec2/metadata.go index 6df3f8a0e7eb..e81124b5323b 100644 --- a/internal/metadataproviders/aws/ec2/metadata.go +++ b/internal/metadataproviders/aws/ec2/metadata.go @@ -5,37 +5,59 @@ package ec2 // import "github.com/open-telemetry/opentelemetry-collector-contrib import ( "context" + "fmt" + "io" - "github.com/aws/aws-sdk-go/aws/ec2metadata" - "github.com/aws/aws-sdk-go/aws/session" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/feature/ec2/imds" ) type Provider interface { - Get(ctx context.Context) (ec2metadata.EC2InstanceIdentityDocument, error) + Get(ctx context.Context) (imds.InstanceIdentityDocument, error) Hostname(ctx context.Context) (string, error) InstanceID(ctx context.Context) (string, error) } type metadataClient struct { - metadata *ec2metadata.EC2Metadata + client *imds.Client } var _ Provider = (*metadataClient)(nil) -func NewProvider(sess *session.Session) Provider { +func NewProvider(cfg aws.Config) Provider { return &metadataClient{ - metadata: ec2metadata.New(sess), + client: imds.NewFromConfig(cfg), } } +func (c *metadataClient) getMetadata(ctx context.Context, path string) (string, error) { + output, err := c.client.GetMetadata(ctx, &imds.GetMetadataInput{Path: path}) + if err != nil { + return "", fmt.Errorf("failed to get %s from IMDS: %w", path, err) + } + defer output.Content.Close() + + data, err := io.ReadAll(output.Content) + if err != nil { + return "", fmt.Errorf("failed to read %s response: %w", path, err) + } + + return string(data), nil +} + func (c *metadataClient) InstanceID(ctx context.Context) (string, error) { - return c.metadata.GetMetadataWithContext(ctx, "instance-id") + return c.getMetadata(ctx, "instance-id") } func (c *metadataClient) Hostname(ctx context.Context) (string, error) { - return c.metadata.GetMetadataWithContext(ctx, "hostname") + return c.getMetadata(ctx, "hostname") } -func (c *metadataClient) Get(ctx context.Context) (ec2metadata.EC2InstanceIdentityDocument, error) { - return c.metadata.GetInstanceIdentityDocumentWithContext(ctx) +func (c *metadataClient) Get(ctx context.Context) (imds.InstanceIdentityDocument, error) { + output, err := c.client.GetInstanceIdentityDocument(ctx, &imds.GetInstanceIdentityDocumentInput{}) + if err != nil { + return imds.InstanceIdentityDocument{}, fmt.Errorf("failed to get instance identity document: %w", err) + } + + return output.InstanceIdentityDocument, nil } diff --git a/internal/metadataproviders/aws/ec2/metadata_test.go b/internal/metadataproviders/aws/ec2/metadata_test.go index 1cdb0f53c497..a55dbd6ebeb2 100644 --- a/internal/metadataproviders/aws/ec2/metadata_test.go +++ b/internal/metadataproviders/aws/ec2/metadata_test.go @@ -4,64 +4,198 @@ package ec2 import ( + "bytes" "context" + "fmt" + "io" + "reflect" "testing" + "time" - "github.com/aws/aws-sdk-go/aws/session" - "github.com/aws/aws-sdk-go/awstesting/mock" - "github.com/stretchr/testify/assert" + "github.com/aws/aws-sdk-go-v2/feature/ec2/imds" ) -func TestMetadataProviderGetError(t *testing.T) { - type args struct { - ctx context.Context - sess *session.Session +type ImdsGetMetadataAPI interface { + GetMetadata(ctx context.Context, params *imds.GetMetadataInput, optFns ...func(*imds.Options)) (*imds.GetMetadataOutput, error) +} + +type ImdsInstanceIdentityDocumentAPI interface { + GetInstanceIdentityDocument(ctx context.Context, params *imds.GetInstanceIdentityDocumentInput, optFns ...func(*imds.Options)) (*imds.GetInstanceIdentityDocumentOutput, error) +} + +func GetMetadataFromImds(ctx context.Context, api ImdsGetMetadataAPI, path string) ([]byte, error) { + output, err := api.GetMetadata(ctx, &imds.GetMetadataInput{ + Path: path, + }) + if err != nil { + return nil, err + } + defer output.Content.Close() + + return io.ReadAll(output.Content) +} + +func GetInstanceIdentityDocumentFromImds(ctx context.Context, api ImdsInstanceIdentityDocumentAPI) (imds.InstanceIdentityDocument, error) { + output, err := api.GetInstanceIdentityDocument(ctx, &imds.GetInstanceIdentityDocumentInput{}) + if err != nil { + return imds.InstanceIdentityDocument{}, err } - tests := []struct { - name string - args args + + return output.InstanceIdentityDocument, nil +} + +type mockGetMetadataAPI func(ctx context.Context, params *imds.GetMetadataInput, optFns ...func(*imds.Options)) (*imds.GetMetadataOutput, error) + +func (m mockGetMetadataAPI) GetMetadata(ctx context.Context, params *imds.GetMetadataInput, optFns ...func(*imds.Options)) (*imds.GetMetadataOutput, error) { + return m(ctx, params, optFns...) +} + +type mockInstanceIdentityDocumentAPI func(ctx context.Context, params *imds.GetInstanceIdentityDocumentInput, optFns ...func(*imds.Options)) (*imds.GetInstanceIdentityDocumentOutput, error) + +func (m mockInstanceIdentityDocumentAPI) GetInstanceIdentityDocument(ctx context.Context, params *imds.GetInstanceIdentityDocumentInput, optFns ...func(*imds.Options)) (*imds.GetInstanceIdentityDocumentOutput, error) { + return m(ctx, params, optFns...) +} + +func TestGetMetadataFromImds(t *testing.T) { + cases := []struct { + name string + client func(t *testing.T) ImdsGetMetadataAPI + path string + expect []byte + wantErr bool }{ { - name: "mock session", - args: args{ - ctx: context.Background(), - sess: mock.Session, + name: "Successfully retrieves InstanceID metadata", + client: func(t *testing.T) ImdsGetMetadataAPI { + return mockGetMetadataAPI(func(ctx context.Context, params *imds.GetMetadataInput, optFns ...func(*imds.Options)) (*imds.GetMetadataOutput, error) { + t.Helper() + if e, a := "instance-id", params.Path; e != a { + t.Errorf("expected Path: %v, got: %v", e, a) + } + return &imds.GetMetadataOutput{ + Content: io.NopCloser(bytes.NewReader([]byte("this is the body foo bar baz"))), + }, nil + }) + }, + path: "instance-id", + expect: []byte("this is the body foo bar baz"), + wantErr: false, + }, + { + name: "Successfully retrieves Hostname metadata", + client: func(t *testing.T) ImdsGetMetadataAPI { + return mockGetMetadataAPI(func(ctx context.Context, params *imds.GetMetadataInput, optFns ...func(*imds.Options)) (*imds.GetMetadataOutput, error) { + t.Helper() + if e, a := "hostname", params.Path; e != a { + t.Errorf("expected Path: %v, got: %v", e, a) + } + return &imds.GetMetadataOutput{ + Content: io.NopCloser(bytes.NewReader([]byte("this is the body foo bar baz"))), + }, nil + }) + }, + path: "hostname", + expect: []byte("this is the body foo bar baz"), + wantErr: false, + }, + { + name: "Path is empty", + client: func(t *testing.T) ImdsGetMetadataAPI { + return mockGetMetadataAPI(func(ctx context.Context, params *imds.GetMetadataInput, optFns ...func(*imds.Options)) (*imds.GetMetadataOutput, error) { + t.Helper() + if params.Path == "" { + return nil, fmt.Errorf("Path cannot be empty") + } + return nil, nil + }) }, + path: "", + expect: nil, + wantErr: true, }, } - for _, tt := range tests { + + for _, tt := range cases { t.Run(tt.name, func(t *testing.T) { - c := NewProvider(tt.args.sess) - _, err := c.Get(tt.args.ctx) - assert.Error(t, err) + ctx := context.TODO() + content, err := GetMetadataFromImds(ctx, tt.client(t), tt.path) + if (err != nil) != tt.wantErr { + t.Fatalf("expected error: %v, got: %v", tt.wantErr, err) + } + if !tt.wantErr && !bytes.Equal(tt.expect, content) { + t.Errorf("expected content: %v, got: %v", string(tt.expect), string(content)) + } }) } } -func TestMetadataProvider_available(t *testing.T) { - type fields struct{} - type args struct { - ctx context.Context - sess *session.Session - } - tests := []struct { - name string - fields fields - args args - want error +func TestInstanceIdentityDocumentFromImds(t *testing.T) { + cases := []struct { + name string + client func(t *testing.T) ImdsInstanceIdentityDocumentAPI + expect imds.InstanceIdentityDocument + wantErr bool }{ { - name: "mock session", - fields: fields{}, - args: args{ctx: context.Background(), sess: mock.Session}, - want: nil, + name: "Successfully retrieves Instance Identity Document", + client: func(t *testing.T) ImdsInstanceIdentityDocumentAPI { + return mockInstanceIdentityDocumentAPI(func(ctx context.Context, params *imds.GetInstanceIdentityDocumentInput, optFns ...func(*imds.Options)) (*imds.GetInstanceIdentityDocumentOutput, error) { + t.Helper() + return &imds.GetInstanceIdentityDocumentOutput{ + InstanceIdentityDocument: imds.InstanceIdentityDocument{ + DevpayProductCodes: []string{"code1", "code2"}, + MarketplaceProductCodes: []string{"market1"}, + AvailabilityZone: "us-west-2a", + PrivateIP: "192.168.1.1", + Version: "2017-09-30", + Region: "us-west-2", + InstanceID: "i-1234567890abcdef0", + BillingProducts: []string{"prod1"}, + InstanceType: "t2.micro", + AccountID: "123456789012", + PendingTime: time.Date(2023, time.January, 1, 0, 0, 0, 0, time.UTC), + ImageID: "ami-abcdef1234567890", + KernelID: "", + RamdiskID: "", + Architecture: "x86_64", + }, + }, nil + }) + }, + expect: imds.InstanceIdentityDocument{ + DevpayProductCodes: []string{"code1", "code2"}, + MarketplaceProductCodes: []string{"market1"}, + AvailabilityZone: "us-west-2a", + PrivateIP: "192.168.1.1", + Version: "2017-09-30", + Region: "us-west-2", + InstanceID: "i-1234567890abcdef0", + BillingProducts: []string{"prod1"}, + InstanceType: "t2.micro", + AccountID: "123456789012", + PendingTime: time.Date(2023, time.January, 1, 0, 0, 0, 0, time.UTC), + ImageID: "ami-abcdef1234567890", + KernelID: "", + RamdiskID: "", + Architecture: "x86_64", + }, + wantErr: false, }, } - for _, tt := range tests { + + for _, tt := range cases { t.Run(tt.name, func(t *testing.T) { - c := NewProvider(tt.args.sess) - _, err := c.InstanceID(tt.args.ctx) - assert.ErrorIs(t, err, tt.want) + ctx := context.TODO() + document, err := GetInstanceIdentityDocumentFromImds(ctx, tt.client(t)) + if (err != nil) != tt.wantErr { + t.Fatalf("expected error: %v, got: %v", tt.wantErr, err) + } + + if !tt.wantErr { + if !reflect.DeepEqual(document, tt.expect) { + t.Errorf("expected document: %+v, got: %+v", tt.expect, document) + } + } }) } } diff --git a/internal/metadataproviders/go.mod b/internal/metadataproviders/go.mod index a15dd7f5e3e0..6f6a1b6461ae 100644 --- a/internal/metadataproviders/go.mod +++ b/internal/metadataproviders/go.mod @@ -4,7 +4,8 @@ go 1.22.0 require ( github.com/Showmax/go-fqdn v1.0.0 - github.com/aws/aws-sdk-go v1.55.5 + github.com/aws/aws-sdk-go-v2 v1.32.6 + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.21 github.com/docker/docker v27.3.1+incompatible github.com/hashicorp/consul/api v1.30.0 github.com/open-telemetry/opentelemetry-collector-contrib/internal/k8sconfig v0.115.0 @@ -22,6 +23,7 @@ require ( require ( github.com/Microsoft/go-winio v0.5.2 // indirect github.com/armon/go-metrics v0.4.1 // indirect + github.com/aws/smithy-go v1.22.1 // indirect github.com/containerd/log v0.1.0 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/distribution/reference v0.5.0 // indirect @@ -53,7 +55,6 @@ require ( github.com/hashicorp/golang-lru v1.0.2 // indirect github.com/hashicorp/serf v0.10.1 // indirect github.com/imdario/mergo v0.3.11 // indirect - github.com/jmespath/go-jmespath v0.4.0 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect diff --git a/internal/metadataproviders/go.sum b/internal/metadataproviders/go.sum index a1621ae24f51..784f8a1d93ed 100644 --- a/internal/metadataproviders/go.sum +++ b/internal/metadataproviders/go.sum @@ -51,8 +51,12 @@ github.com/armon/go-metrics v0.4.1/go.mod h1:E6amYzXo6aW1tqzoZGT755KkbgrJsSdpwZ+ github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= -github.com/aws/aws-sdk-go v1.55.5 h1:KKUZBfBoyqy5d3swXyiC7Q76ic40rYcbqH7qjh59kzU= -github.com/aws/aws-sdk-go v1.55.5/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU= +github.com/aws/aws-sdk-go-v2 v1.32.6 h1:7BokKRgRPuGmKkFMhEg/jSul+tB9VvXhcViILtfG8b4= +github.com/aws/aws-sdk-go-v2 v1.32.6/go.mod h1:P5WJBrYqqbWVaOxgH0X/FYYD47/nooaPOZPlQdmiN2U= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.21 h1:AmoU1pziydclFT/xRV+xXE/Vb8fttJCLRPv8oAkprc0= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.21/go.mod h1:AjUdLYe4Tgs6kpH4Bv7uMZo7pottoyHMn4eTcIcneaY= +github.com/aws/smithy-go v1.22.1 h1:/HPHZQ0g7f4eUeK6HKglFz8uwVfZKgoI25rb/J+dnro= +github.com/aws/smithy-go v1.22.1/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= @@ -257,10 +261,6 @@ github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1: github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= github.com/imdario/mergo v0.3.11 h1:3tnifQM4i+fbajXKBHXWEH+KvNHqojZ778UH75j3bGA= github.com/imdario/mergo v0.3.11/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= -github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg= -github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo= -github.com/jmespath/go-jmespath/internal/testify v1.5.1 h1:shLQSRRSCCPj3f2gpwzGwWFoC7ycTf1rcQZHOlsJ6N8= -github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= diff --git a/processor/resourcedetectionprocessor/go.mod b/processor/resourcedetectionprocessor/go.mod index 76e68e8e4996..c6b39518f358 100644 --- a/processor/resourcedetectionprocessor/go.mod +++ b/processor/resourcedetectionprocessor/go.mod @@ -6,6 +6,10 @@ require ( cloud.google.com/go/compute/metadata v0.5.2 github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.25.0 github.com/aws/aws-sdk-go v1.55.5 + github.com/aws/aws-sdk-go-v2 v1.32.6 + github.com/aws/aws-sdk-go-v2/config v1.28.6 + github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.21 + github.com/aws/aws-sdk-go-v2/service/ec2 v1.196.0 github.com/google/go-cmp v0.6.0 github.com/hashicorp/consul/api v1.30.0 github.com/open-telemetry/opentelemetry-collector-contrib/internal/aws/ecsutil v0.115.0 @@ -42,6 +46,16 @@ require ( github.com/Microsoft/go-winio v0.6.1 // indirect github.com/Showmax/go-fqdn v1.0.0 // indirect github.com/armon/go-metrics v0.4.1 // indirect + github.com/aws/aws-sdk-go-v2/credentials v1.17.47 // indirect + github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.25 // indirect + github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.25 // indirect + github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.1 // indirect + github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.6 // indirect + github.com/aws/aws-sdk-go-v2/service/sso v1.24.7 // indirect + github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.6 // indirect + github.com/aws/aws-sdk-go-v2/service/sts v1.33.2 // indirect + github.com/aws/smithy-go v1.22.1 // indirect github.com/cenkalti/backoff/v4 v4.3.0 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/distribution/reference v0.5.0 // indirect diff --git a/processor/resourcedetectionprocessor/go.sum b/processor/resourcedetectionprocessor/go.sum index 29b992b16ab2..83f627675e23 100644 --- a/processor/resourcedetectionprocessor/go.sum +++ b/processor/resourcedetectionprocessor/go.sum @@ -57,6 +57,34 @@ github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgI github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= github.com/aws/aws-sdk-go v1.55.5 h1:KKUZBfBoyqy5d3swXyiC7Q76ic40rYcbqH7qjh59kzU= github.com/aws/aws-sdk-go v1.55.5/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU= +github.com/aws/aws-sdk-go-v2 v1.32.6 h1:7BokKRgRPuGmKkFMhEg/jSul+tB9VvXhcViILtfG8b4= +github.com/aws/aws-sdk-go-v2 v1.32.6/go.mod h1:P5WJBrYqqbWVaOxgH0X/FYYD47/nooaPOZPlQdmiN2U= +github.com/aws/aws-sdk-go-v2/config v1.28.6 h1:D89IKtGrs/I3QXOLNTH93NJYtDhm8SYa9Q5CsPShmyo= +github.com/aws/aws-sdk-go-v2/config v1.28.6/go.mod h1:GDzxJ5wyyFSCoLkS+UhGB0dArhb9mI+Co4dHtoTxbko= +github.com/aws/aws-sdk-go-v2/credentials v1.17.47 h1:48bA+3/fCdi2yAwVt+3COvmatZ6jUDNkDTIsqDiMUdw= +github.com/aws/aws-sdk-go-v2/credentials v1.17.47/go.mod h1:+KdckOejLW3Ks3b0E3b5rHsr2f9yuORBum0WPnE5o5w= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.21 h1:AmoU1pziydclFT/xRV+xXE/Vb8fttJCLRPv8oAkprc0= +github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.21/go.mod h1:AjUdLYe4Tgs6kpH4Bv7uMZo7pottoyHMn4eTcIcneaY= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.25 h1:s/fF4+yDQDoElYhfIVvSNyeCydfbuTKzhxSXDXCPasU= +github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.25/go.mod h1:IgPfDv5jqFIzQSNbUEMoitNooSMXjRSDkhXv8jiROvU= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.25 h1:ZntTCl5EsYnhN/IygQEUugpdwbhdkom9uHcbCftiGgA= +github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.25/go.mod h1:DBdPrgeocww+CSl1C8cEV8PN1mHMBhuCDLpXezyvWkE= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 h1:VaRN3TlFdd6KxX1x3ILT5ynH6HvKgqdiXoTxAF4HQcQ= +github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1/go.mod h1:FbtygfRFze9usAadmnGJNc8KsP346kEe+y2/oyhGAGc= +github.com/aws/aws-sdk-go-v2/service/ec2 v1.196.0 h1:ZBtoihAqfT+5b1FwGHOubq8k10KwaIyKZd2/CRTucAU= +github.com/aws/aws-sdk-go-v2/service/ec2 v1.196.0/go.mod h1:00zqVNJFK6UASrTnuvjJHJuaqUdkVz5tW8Ip+VhzuNg= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.1 h1:iXtILhvDxB6kPvEXgsDhGaZCSC6LQET5ZHSdJozeI0Y= +github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.1/go.mod h1:9nu0fVANtYiAePIBh2/pFUSwtJ402hLnp854CNoDOeE= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.6 h1:50+XsN70RS7dwJ2CkVNXzj7U2L1HKP8nqTd3XWEXBN4= +github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.6/go.mod h1:WqgLmwY7so32kG01zD8CPTJWVWM+TzJoOVHwTg4aPug= +github.com/aws/aws-sdk-go-v2/service/sso v1.24.7 h1:rLnYAfXQ3YAccocshIH5mzNNwZBkBo+bP6EhIxak6Hw= +github.com/aws/aws-sdk-go-v2/service/sso v1.24.7/go.mod h1:ZHtuQJ6t9A/+YDuxOLnbryAmITtr8UysSny3qcyvJTc= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.6 h1:JnhTZR3PiYDNKlXy50/pNeix9aGMo6lLpXwJ1mw8MD4= +github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.6/go.mod h1:URronUEGfXZN1VpdktPSD1EkAL9mfrV+2F4sjH38qOY= +github.com/aws/aws-sdk-go-v2/service/sts v1.33.2 h1:s4074ZO1Hk8qv65GqNXqDjmkf4HSQqJukaLuuW0TpDA= +github.com/aws/aws-sdk-go-v2/service/sts v1.33.2/go.mod h1:mVggCnIWoM09jP71Wh+ea7+5gAp53q+49wDFs1SW5z8= +github.com/aws/smithy-go v1.22.1 h1:/HPHZQ0g7f4eUeK6HKglFz8uwVfZKgoI25rb/J+dnro= +github.com/aws/smithy-go v1.22.1/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= diff --git a/processor/resourcedetectionprocessor/internal/aws/ec2/ec2.go b/processor/resourcedetectionprocessor/internal/aws/ec2/ec2.go index a785030e4f40..44b3e543270e 100644 --- a/processor/resourcedetectionprocessor/internal/aws/ec2/ec2.go +++ b/processor/resourcedetectionprocessor/internal/aws/ec2/ec2.go @@ -9,10 +9,12 @@ import ( "net/http" "regexp" - "github.com/aws/aws-sdk-go/aws" - "github.com/aws/aws-sdk-go/aws/session" - "github.com/aws/aws-sdk-go/service/ec2" - "github.com/aws/aws-sdk-go/service/ec2/ec2iface" + "github.com/aws/aws-sdk-go-v2/config" + "github.com/aws/aws-sdk-go-v2/service/ec2" + "github.com/aws/aws-sdk-go-v2/service/ec2/types" + + "github.com/aws/aws-sdk-go-v2/aws" + "go.opentelemetry.io/collector/pdata/pcommon" "go.opentelemetry.io/collector/processor" conventions "go.opentelemetry.io/collector/semconv/v1.6.1" @@ -32,21 +34,21 @@ const ( var _ internal.Detector = (*Detector)(nil) type ec2ifaceBuilder interface { - buildClient(region string, client *http.Client) (ec2iface.EC2API, error) + buildClient(ctx context.Context, region string, client *http.Client) (ec2.DescribeTagsAPIClient, error) } type ec2ClientBuilder struct{} -func (e *ec2ClientBuilder) buildClient(region string, client *http.Client) (ec2iface.EC2API, error) { - sess, err := session.NewSession(&aws.Config{ - Region: aws.String(region), - HTTPClient: client, - }, +func (e *ec2ClientBuilder) buildClient(ctx context.Context, region string, client *http.Client) (ec2.DescribeTagsAPIClient, error) { + cfg, err := config.LoadDefaultConfig(ctx, + config.WithRegion(region), + config.WithHTTPClient(client), ) if err != nil { return nil, err } - return ec2.New(sess), nil + + return ec2.NewFromConfig(cfg), nil } type Detector struct { @@ -59,7 +61,7 @@ type Detector struct { func NewDetector(set processor.Settings, dcfg internal.DetectorConfig) (internal.Detector, error) { cfg := dcfg.(Config) - sess, err := session.NewSession() + awsConfig, err := config.LoadDefaultConfig(context.Background()) if err != nil { return nil, err } @@ -69,7 +71,7 @@ func NewDetector(set processor.Settings, dcfg internal.DetectorConfig) (internal } return &Detector{ - metadataProvider: ec2provider.NewProvider(sess), + metadataProvider: ec2provider.NewProvider(awsConfig), tagKeyRegexes: tagKeyRegexes, logger: set.Logger, rb: metadata.NewResourceBuilder(cfg.ResourceAttributes), @@ -106,12 +108,12 @@ func (d *Detector) Detect(ctx context.Context) (resource pcommon.Resource, schem if len(d.tagKeyRegexes) != 0 { httpClient := getClientConfig(ctx, d.logger) - ec2Client, err := d.ec2ClientBuilder.buildClient(meta.Region, httpClient) + ec2Client, err := d.ec2ClientBuilder.buildClient(ctx, meta.Region, httpClient) if err != nil { d.logger.Warn("failed to build ec2 client", zap.Error(err)) return res, conventions.SchemaURL, nil } - tags, err := fetchEC2Tags(ec2Client, meta.InstanceID, d.tagKeyRegexes) + tags, err := fetchEC2Tags(ctx, ec2Client, meta.InstanceID, d.tagKeyRegexes) if err != nil { d.logger.Warn("failed fetching ec2 instance tags", zap.Error(err)) } else { @@ -132,13 +134,11 @@ func getClientConfig(ctx context.Context, logger *zap.Logger) *http.Client { return client } -func fetchEC2Tags(svc ec2iface.EC2API, instanceID string, tagKeyRegexes []*regexp.Regexp) (map[string]string, error) { - ec2Tags, err := svc.DescribeTags(&ec2.DescribeTagsInput{ - Filters: []*ec2.Filter{{ - Name: aws.String("resource-id"), - Values: []*string{ - aws.String(instanceID), - }, +func fetchEC2Tags(ctx context.Context, svc ec2.DescribeTagsAPIClient, instanceID string, tagKeyRegexes []*regexp.Regexp) (map[string]string, error) { + ec2Tags, err := svc.DescribeTags(ctx, &ec2.DescribeTagsInput{ + Filters: []types.Filter{{ + Name: aws.String("resource-id"), + Values: []string{instanceID}, }}, }) if err != nil { diff --git a/processor/resourcedetectionprocessor/internal/aws/ec2/ec2_test.go b/processor/resourcedetectionprocessor/internal/aws/ec2/ec2_test.go index 4925b8a6b9a4..4c3341d0c84d 100644 --- a/processor/resourcedetectionprocessor/internal/aws/ec2/ec2_test.go +++ b/processor/resourcedetectionprocessor/internal/aws/ec2/ec2_test.go @@ -10,9 +10,11 @@ import ( "regexp" "testing" - "github.com/aws/aws-sdk-go/aws/ec2metadata" - "github.com/aws/aws-sdk-go/service/ec2" - "github.com/aws/aws-sdk-go/service/ec2/ec2iface" + "github.com/aws/aws-sdk-go-v2/aws" + "github.com/aws/aws-sdk-go-v2/feature/ec2/imds" + + "github.com/aws/aws-sdk-go-v2/service/ec2" + ec2types "github.com/aws/aws-sdk-go-v2/service/ec2/types" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "go.opentelemetry.io/collector/pdata/pcommon" @@ -26,7 +28,7 @@ import ( var errUnavailable = errors.New("ec2metadata unavailable") type mockMetadata struct { - retIDDoc ec2metadata.EC2InstanceIdentityDocument + retIDDoc imds.InstanceIdentityDocument retErrIDDoc error retHostname string @@ -39,13 +41,13 @@ var _ ec2provider.Provider = (*mockMetadata)(nil) type mockClientBuilder struct{} -func (e *mockClientBuilder) buildClient(_ string, _ *http.Client) (ec2iface.EC2API, error) { +func (e *mockClientBuilder) buildClient(_ context.Context, _ string, _ *http.Client) (ec2.DescribeTagsAPIClient, error) { return &mockEC2Client{}, nil } type mockClientBuilderError struct{} -func (e *mockClientBuilderError) buildClient(_ string, _ *http.Client) (ec2iface.EC2API, error) { +func (e *mockClientBuilderError) buildClient(_ context.Context, _ string, _ *http.Client) (ec2.DescribeTagsAPIClient, error) { return &mockEC2ClientError{}, nil } @@ -56,9 +58,9 @@ func (mm mockMetadata) InstanceID(_ context.Context) (string, error) { return "", nil } -func (mm mockMetadata) Get(_ context.Context) (ec2metadata.EC2InstanceIdentityDocument, error) { +func (mm mockMetadata) Get(_ context.Context) (imds.InstanceIdentityDocument, error) { if mm.retErrIDDoc != nil { - return ec2metadata.EC2InstanceIdentityDocument{}, mm.retErrIDDoc + return imds.InstanceIdentityDocument{}, mm.retErrIDDoc } return mm.retIDDoc, nil } @@ -111,36 +113,35 @@ func TestNewDetector(t *testing.T) { } // Define a mock client to mock connecting to an EC2 instance -type mockEC2ClientError struct { - ec2iface.EC2API -} +type mockEC2ClientError struct{} // override the DescribeTags function to mock the output from an actual EC2 instance -func (m *mockEC2ClientError) DescribeTags(_ *ec2.DescribeTagsInput) (*ec2.DescribeTagsOutput, error) { +func (m *mockEC2ClientError) DescribeTags(_ context.Context, _ *ec2.DescribeTagsInput, _ ...func(*ec2.Options)) (*ec2.DescribeTagsOutput, error) { return nil, errors.New("Error fetching tags") } -type mockEC2Client struct { - ec2iface.EC2API -} +type mockEC2Client struct{} // override the DescribeTags function to mock the output from an actual EC2 instance -func (m *mockEC2Client) DescribeTags(input *ec2.DescribeTagsInput) (*ec2.DescribeTagsOutput, error) { - if *input.Filters[0].Values[0] == "error" { +func (m *mockEC2Client) DescribeTags(_ context.Context, input *ec2.DescribeTagsInput, _ ...func(*ec2.Options)) (*ec2.DescribeTagsOutput, error) { + if len(input.Filters) > 0 && len(input.Filters[0].Values) > 0 && input.Filters[0].Values[0] == "error" { return nil, errors.New("error") } - tag1 := "tag1" - tag2 := "tag2" - resource1 := "resource1" - val1 := "val1" - val2 := "val2" - resourceType := "type" - return &ec2.DescribeTagsOutput{ - Tags: []*ec2.TagDescription{ - {Key: &tag1, ResourceId: &resource1, ResourceType: &resourceType, Value: &val1}, - {Key: &tag2, ResourceId: &resource1, ResourceType: &resourceType, Value: &val2}, + Tags: []ec2types.TagDescription{ + { + Key: aws.String("tag1"), + ResourceId: aws.String("resource1"), + ResourceType: "type", + Value: aws.String("val1"), + }, + { + Key: aws.String("tag2"), + ResourceId: aws.String("resource1"), + ResourceType: "type", + Value: aws.String("val2"), + }, }, }, nil } @@ -164,7 +165,7 @@ func TestDetector_Detect(t *testing.T) { { name: "success", fields: fields{metadataProvider: &mockMetadata{ - retIDDoc: ec2metadata.EC2InstanceIdentityDocument{ + retIDDoc: imds.InstanceIdentityDocument{ Region: "us-west-2", AccountID: "account1234", AvailabilityZone: "us-west-2a", @@ -194,7 +195,7 @@ func TestDetector_Detect(t *testing.T) { { name: "success with tags", fields: fields{metadataProvider: &mockMetadata{ - retIDDoc: ec2metadata.EC2InstanceIdentityDocument{ + retIDDoc: imds.InstanceIdentityDocument{ Region: "us-west-2", AccountID: "account1234", AvailabilityZone: "us-west-2a", @@ -228,7 +229,7 @@ func TestDetector_Detect(t *testing.T) { { name: "success without tags returned from describeTags", fields: fields{metadataProvider: &mockMetadata{ - retIDDoc: ec2metadata.EC2InstanceIdentityDocument{ + retIDDoc: imds.InstanceIdentityDocument{ Region: "us-west-2", AccountID: "account1234", AvailabilityZone: "us-west-2a", @@ -259,7 +260,7 @@ func TestDetector_Detect(t *testing.T) { { name: "endpoint not available", fields: fields{metadataProvider: &mockMetadata{ - retIDDoc: ec2metadata.EC2InstanceIdentityDocument{}, + retIDDoc: imds.InstanceIdentityDocument{}, retErrIDDoc: errors.New("should not be called"), isAvailable: false, }}, @@ -270,7 +271,7 @@ func TestDetector_Detect(t *testing.T) { { name: "get fails", fields: fields{metadataProvider: &mockMetadata{ - retIDDoc: ec2metadata.EC2InstanceIdentityDocument{}, + retIDDoc: imds.InstanceIdentityDocument{}, retErrIDDoc: errors.New("get failed"), isAvailable: true, }}, @@ -281,7 +282,7 @@ func TestDetector_Detect(t *testing.T) { { name: "hostname fails", fields: fields{metadataProvider: &mockMetadata{ - retIDDoc: ec2metadata.EC2InstanceIdentityDocument{}, + retIDDoc: imds.InstanceIdentityDocument{}, retHostname: "", retErrHostname: errors.New("hostname failed"), isAvailable: true, @@ -354,7 +355,7 @@ func TestEC2Tags(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { m := &mockEC2Client{} - output, err := fetchEC2Tags(m, tt.resourceID, tt.tagKeyRegexes) + output, err := fetchEC2Tags(context.Background(), m, tt.resourceID, tt.tagKeyRegexes) if tt.shouldError { assert.Error(t, err) return