Skip to content

Commit 5f4fce1

Browse files
#201 - AWSEKSResourceDetector - Validate ClusterName/ContainerID independently before adding it to the resource (#205)
- Validates ClusterName/ContainerID independently before adding it to the resource - Includes bug fix - IsEKSProcess should return non-null auth value to confirm if its running in EKS environment. - Handled exceptions separately with more error information - Added Unit Tests Co-authored-by: Prashant Srivastava <50466688+srprash@users.noreply.github.com>
1 parent 667fc49 commit 5f4fce1

2 files changed

Lines changed: 96 additions & 46 deletions

File tree

src/OpenTelemetry.Contrib.Extensions.AWSXRay/Resources/AWSEKSResourceDetector.cs

Lines changed: 65 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -40,26 +40,15 @@ public class AWSEKSResourceDetector : IResourceDetector
4040
/// <returns>List of key-value pairs of resource attributes.</returns>
4141
public IEnumerable<KeyValuePair<string, object>> Detect()
4242
{
43-
List<KeyValuePair<string, object>> resourceAttributes = null;
44-
45-
try
46-
{
47-
var clusterName = this.GetEKSClusterName(AWSEKSCredentialPath);
48-
var containerId = this.GetEKSContainerId(AWSEKSMetadataFilePath);
49-
50-
if (clusterName == null && containerId == null)
51-
{
52-
return resourceAttributes;
53-
}
54-
55-
resourceAttributes = this.ExtractResourceAttributes(clusterName, containerId);
56-
}
57-
catch (Exception ex)
43+
var credentials = this.GetEKSCredentials(AWSEKSCredentialPath);
44+
if (credentials == null || !this.IsEKSProcess(credentials))
5845
{
59-
AWSXRayEventSource.Log.ResourceAttributesExtractException(nameof(AWSEKSResourceDetector), ex);
46+
return null;
6047
}
6148

62-
return resourceAttributes;
49+
return this.ExtractResourceAttributes(
50+
this.GetEKSClusterName(credentials),
51+
this.GetEKSContainerId(AWSEKSMetadataFilePath));
6352
}
6453

6554
internal List<KeyValuePair<string, object>> ExtractResourceAttributes(string clusterName, string containerId)
@@ -68,73 +57,103 @@ internal List<KeyValuePair<string, object>> ExtractResourceAttributes(string clu
6857
{
6958
new KeyValuePair<string, object>(AWSSemanticConventions.AttributeCloudProvider, "aws"),
7059
new KeyValuePair<string, object>(AWSSemanticConventions.AttributeCloudPlatform, "aws_eks"),
71-
new KeyValuePair<string, object>(AWSSemanticConventions.AttributeK8SClusterName, clusterName),
72-
new KeyValuePair<string, object>(AWSSemanticConventions.AttributeContainerID, containerId),
7360
};
7461

62+
if (!string.IsNullOrEmpty(clusterName))
63+
{
64+
resourceAttributes.Add(new KeyValuePair<string, object>(AWSSemanticConventions.AttributeK8SClusterName, clusterName));
65+
}
66+
67+
if (!string.IsNullOrEmpty(containerId))
68+
{
69+
resourceAttributes.Add(new KeyValuePair<string, object>(AWSSemanticConventions.AttributeContainerID, containerId));
70+
}
71+
7572
return resourceAttributes;
7673
}
7774

7875
internal string GetEKSCredentials(string path)
7976
{
80-
StringBuilder stringBuilder = new StringBuilder();
81-
82-
using (var streamReader = ResourceDetectorUtils.GetStreamReader(path))
77+
try
8378
{
84-
while (!streamReader.EndOfStream)
79+
StringBuilder stringBuilder = new StringBuilder();
80+
81+
using (var streamReader = ResourceDetectorUtils.GetStreamReader(path))
8582
{
86-
stringBuilder.Append(streamReader.ReadLine().Trim());
83+
while (!streamReader.EndOfStream)
84+
{
85+
stringBuilder.Append(streamReader.ReadLine().Trim());
86+
}
8787
}
88+
89+
return "Bearer " + stringBuilder.ToString();
90+
}
91+
catch (Exception ex)
92+
{
93+
AWSXRayEventSource.Log.ResourceAttributesExtractException($"{nameof(AWSEKSResourceDetector)} : Failed to load client token", ex);
8894
}
8995

90-
return "Bearer " + stringBuilder.ToString();
96+
return null;
9197
}
9298

9399
internal string GetEKSContainerId(string path)
94100
{
95-
string containerId = null;
96-
97-
using (var streamReader = ResourceDetectorUtils.GetStreamReader(path))
101+
try
98102
{
99-
while (!streamReader.EndOfStream)
103+
using (var streamReader = ResourceDetectorUtils.GetStreamReader(path))
100104
{
101-
var trimmedLine = streamReader.ReadLine().Trim();
102-
if (trimmedLine.Length > 64)
105+
while (!streamReader.EndOfStream)
103106
{
104-
containerId = trimmedLine.Substring(trimmedLine.Length - 64);
105-
return containerId;
107+
var trimmedLine = streamReader.ReadLine().Trim();
108+
if (trimmedLine.Length > 64)
109+
{
110+
return trimmedLine.Substring(trimmedLine.Length - 64);
111+
}
106112
}
107113
}
108114
}
115+
catch (Exception ex)
116+
{
117+
AWSXRayEventSource.Log.ResourceAttributesExtractException($"{nameof(AWSEKSResourceDetector)} : Failed to get Container Id", ex);
118+
}
109119

110-
return containerId;
120+
return null;
111121
}
112122

113123
internal AWSEKSClusterInformationModel DeserializeResponse(string response)
114124
{
115125
return ResourceDetectorUtils.DeserializeFromString<AWSEKSClusterInformationModel>(response);
116126
}
117127

118-
private string GetEKSClusterName(string path)
128+
private string GetEKSClusterName(string credentials)
119129
{
120-
var credentials = this.GetEKSCredentials(path);
121-
122-
if (!this.IsEKSProcess(credentials))
130+
try
123131
{
124-
return null;
132+
var clusterInfo = this.GetEKSClusterInfo(credentials);
133+
return this.DeserializeResponse(clusterInfo)?.Data?.ClusterName;
134+
}
135+
catch (Exception ex)
136+
{
137+
AWSXRayEventSource.Log.ResourceAttributesExtractException($"{nameof(AWSEKSResourceDetector)} : Failed to get cluster information", ex);
125138
}
126139

127-
var clusterInfo = this.GetEKSClusterInfo(credentials);
128-
var clusterInfoObject = this.DeserializeResponse(clusterInfo);
129-
130-
return clusterInfoObject.Data?.ClusterName;
140+
return null;
131141
}
132142

133143
private bool IsEKSProcess(string credentials)
134144
{
135-
var httpClientHandler = this.CreateHttpClientHandler();
136-
var awsAuth = ResourceDetectorUtils.SendOutRequest(AWSAuthUrl, "GET", new KeyValuePair<string, string>("Authorization", credentials), httpClientHandler).Result;
137-
return string.IsNullOrEmpty(awsAuth);
145+
string awsAuth = null;
146+
try
147+
{
148+
var httpClientHandler = this.CreateHttpClientHandler();
149+
awsAuth = ResourceDetectorUtils.SendOutRequest(AWSAuthUrl, "GET", new KeyValuePair<string, string>("Authorization", credentials), httpClientHandler).Result;
150+
}
151+
catch (Exception ex)
152+
{
153+
AWSXRayEventSource.Log.ResourceAttributesExtractException($"{nameof(AWSEKSResourceDetector)} : Failed to get EKS information", ex);
154+
}
155+
156+
return !string.IsNullOrEmpty(awsAuth);
138157
}
139158

140159
private string GetEKSClusterInfo(string credentials)

test/OpenTelemetry.Contrib.Extensions.AWSXRay.Tests/Resources/TestAWSEKSResourceDetector.cs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,43 @@ public void TestExtractResourceAttributes()
4444

4545
var resourceAttributes = eksResourceDetector.ExtractResourceAttributes(clusterName, containerId).ToDictionary(x => x.Key, x => x.Value);
4646

47+
Assert.Equal(4, resourceAttributes.Count);
4748
Assert.Equal("aws", resourceAttributes[AWSSemanticConventions.AttributeCloudProvider]);
4849
Assert.Equal("aws_eks", resourceAttributes[AWSSemanticConventions.AttributeCloudPlatform]);
4950
Assert.Equal("Test cluster name", resourceAttributes[AWSSemanticConventions.AttributeK8SClusterName]);
5051
Assert.Equal("Test container id", resourceAttributes[AWSSemanticConventions.AttributeContainerID]);
5152
}
5253

54+
[Fact]
55+
public void TestExtractResourceAttributesWithEmptyClusterName()
56+
{
57+
var eksResourceDetector = new AWSEKSResourceDetector();
58+
var containerId = "Test container id";
59+
60+
var resourceAttributes = eksResourceDetector.ExtractResourceAttributes(string.Empty, containerId).ToDictionary(x => x.Key, x => x.Value);
61+
62+
// Validate the count of resourceAttributes -> Excluding cluster name, there will be only three resourceAttributes
63+
Assert.Equal(3, resourceAttributes.Count);
64+
Assert.Equal("aws", resourceAttributes[AWSSemanticConventions.AttributeCloudProvider]);
65+
Assert.Equal("aws_eks", resourceAttributes[AWSSemanticConventions.AttributeCloudPlatform]);
66+
Assert.Equal("Test container id", resourceAttributes[AWSSemanticConventions.AttributeContainerID]);
67+
}
68+
69+
[Fact]
70+
public void TestExtractResourceAttributesWithEmptyContainerId()
71+
{
72+
var eksResourceDetector = new AWSEKSResourceDetector();
73+
var clusterName = "Test cluster name";
74+
75+
var resourceAttributes = eksResourceDetector.ExtractResourceAttributes(clusterName, string.Empty).ToDictionary(x => x.Key, x => x.Value);
76+
77+
// Validate the count of resourceAttributes -> Excluding container id, there will be only three resourceAttributes
78+
Assert.Equal(3, resourceAttributes.Count);
79+
Assert.Equal("aws", resourceAttributes[AWSSemanticConventions.AttributeCloudProvider]);
80+
Assert.Equal("aws_eks", resourceAttributes[AWSSemanticConventions.AttributeCloudPlatform]);
81+
Assert.Equal("Test cluster name", resourceAttributes[AWSSemanticConventions.AttributeK8SClusterName]);
82+
}
83+
5384
[Fact]
5485
public void TestGetEKSCredentials()
5586
{

0 commit comments

Comments
 (0)