-
Notifications
You must be signed in to change notification settings - Fork 1.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
CSHARP-4718: Enable Container and kubernetes awareness #1295
Conversation
@@ -176,6 +179,23 @@ name switch | |||
_ => null, | |||
}; | |||
|
|||
BsonDocument GetContainerDocument() | |||
{ | |||
var isExecutionContainerDocker = File.Exists("/.dockerenv"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I hesitated a little about checking for existence of a file to detect if we are in a docker container. Doing this makes us a dependent on the file system which might have potential issues related to file permissions or availability. I did some digging and found there is a environment variable called DOTNET_RUNNING_IN_CONTAINER
which is set automatically by official Microsoft .Net images More info . Problem is using this environment variable relies on the .net runtime to set it which is guaranteed if users use the official .Net images for their docker containers. However, it doesn't cover cases where users don't use the official .net images or choose to manually install a .net runtime in their containers. So I think checking for the file existence is our best bet unless we want to use both strategies and let them compensate for each other?
@@ -132,6 +132,17 @@ public void CreateDriverDocument_should_return_expected_result() | |||
result.Should().Be($"{{ name : 'mongo-csharp-driver', version : '{driverVersion}' }}"); | |||
} | |||
|
|||
[Fact] | |||
public void CreateEnvDocument_should_return_expected_result() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using file existence as check for docker container presence means we can't really unit test it because we can't easily mock FIle.Exist
as it is a static class. There is a way to bypass that but it will mean complicating the code for checking docker container presence just for the sake of testing. However, I manually tested by running a mongodb .net application in a docker container with the changes to test and the docker detection logic works.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See mine comment above.
BsonDocument GetContainerDocument() | ||
{ | ||
var isExecutionContainerDocker = File.Exists("/.dockerenv"); | ||
var isOrchestratorKubernetes = Environment.GetEnvironmentVariable("KUBERNETES_SERVICE_HOST") != null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It might makes sense to use EnvironmentVariableProvider
here. It might be substitutable and it will help us when we will approach task to run tests in parallel.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We probably ought to implement something similar for file system. With the same motivation: having such substitutable components could help us to isolate each test without necessarily to have file on the host machine or setting environment variables, as each such host adjustment could affect other tests.
@@ -132,6 +132,17 @@ public void CreateDriverDocument_should_return_expected_result() | |||
result.Should().Be($"{{ name : 'mongo-csharp-driver', version : '{driverVersion}' }}"); | |||
} | |||
|
|||
[Fact] | |||
public void CreateEnvDocument_should_return_expected_result() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See mine comment above.
@@ -176,6 +179,23 @@ name switch | |||
_ => null, | |||
}; | |||
|
|||
BsonDocument GetContainerDocument() | |||
{ | |||
var isExecutionContainerDocker = File.Exists("/.dockerenv"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is Windows file system OK with such check? Should we wrap this with try-catch (some permissions restriction could lead to exception I suppose)?
BTW, this check looks like a Linux container detection. What about Windows containers? Should we try to detect them as well?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looking good. I'm OK with the current impl or switching to our own mocks for IFileSystem
and IEnvironment
(or whatever we want to call it. We do need the two additional test cases noted.
As for Windows container detection, if we find a way to reliably detect Docker on Windows, then we need to create a new DRIVERS ticket and update the spec so all drivers perform the detection in the same way.
result.Should().Be($"{{ name : 'vercel', container : {{ orchestrator : 'kubernetes' }} }}"); | ||
} | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should also verify:
client.env.container.runtime
is set todocker
when/.dockerenv
is present.client.env.container
is not present if neither Docker nor Kubernetes is deteced.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done. Also I think I found a reliable way to detect Docker for Windows. I will reach out the owners of the DRIVERS ticket for this work to discuss further if spec needs to be updated or if we are ok with drivers not detecting Windows containers given their low usage.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good, minor changes requested.
|
||
private static void Initialize() | ||
{ | ||
__driverDocument = new Lazy<BsonDocument>(CreateDriverDocument); | ||
__envDocument = new Lazy<BsonDocument>(CreateEnvDocument); | ||
__osDocument = new Lazy<BsonDocument>(CreateOSDocument); | ||
__platformString = new Lazy<string>(GetPlatformString); | ||
__environmentVariableProvider = new Lazy<IEnvironmentVariableProvider>(() => new EnvironmentVariableProvider()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why it's Lazy? It could point to EnvironmentVariableProvider.Instance
by default.
|
||
private static void Initialize() | ||
{ | ||
__driverDocument = new Lazy<BsonDocument>(CreateDriverDocument); | ||
__envDocument = new Lazy<BsonDocument>(CreateEnvDocument); | ||
__osDocument = new Lazy<BsonDocument>(CreateOSDocument); | ||
__platformString = new Lazy<string>(GetPlatformString); | ||
__environmentVariableProvider = new Lazy<IEnvironmentVariableProvider>(() => new EnvironmentVariableProvider()); | ||
__fileSystemProvider = new Lazy<IFileSystemProvider>(() => new FileSystemProvider()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same here: I suppose we do not need Lazy, just use Instance by default.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, some minor comments for your consideration.
File and environment vars mocking approach is a great addition.
bool Exists(string name); | ||
} | ||
|
||
internal class FileWrapper : IFile |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
minor: sealed?
internal class FileSystemProvider : IFileSystemProvider | ||
{ | ||
private static readonly IFileSystemProvider __instance = new FileSystemProvider(); | ||
public static IFileSystemProvider Instance => __instance; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
minor: maybe read-only property is sufficient ?
public static IFileSystemProvider Instance { get; } = new FileSystemProvider();
@@ -30,17 +31,31 @@ internal class ClientDocumentHelper | |||
private static Lazy<BsonDocument> __envDocument; | |||
private static Lazy<BsonDocument> __osDocument; | |||
private static Lazy<string> __platformString; | |||
private static IEnvironmentVariableProvider __environmentVariableProvider; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we want to use __environmentVariableProvider
for all other variables in this file?
Follow up ticket for that? This is also pre-requisite for future tests parallelization.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes a follow up is to be made.
|
||
ClientDocumentHelper.SetEnvironmentVariableProvider(environmentVariableProviderMock.Object); | ||
ClientDocumentHelper.SetFileSystemProvider(fileSystemProviderMock.Object); | ||
using (new DisposableEnvironmentVariable("VERCEL")) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ideally we'd just use environmentVariableProviderMock
for "VERCEL".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah this is connected to replacing uses of Environment with EnvironmentVariableProvider in ClientDocumentHelper.cs
|
||
if (isExecutionContainerDocker || isOrchestratorKubernetes) | ||
{ | ||
return new BsonDocument |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
minor: styling shortcut for your consideration
return new()
{
....
}
Enables container and kubernetes awareness in the driver as specified in the MongoDB Handshake Spec .
What is the motivation for this change?