Skip to content
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

feat: Update CosmosDb image to vnext-preview version #1324

Open
wants to merge 8 commits into
base: develop
Choose a base branch
from
28 changes: 14 additions & 14 deletions src/Testcontainers.CosmosDb/CosmosDbBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ namespace Testcontainers.CosmosDb;
[PublicAPI]
public sealed class CosmosDbBuilder : ContainerBuilder<CosmosDbBuilder, CosmosDbContainer, CosmosDbConfiguration>
{
public const string CosmosDbImage = "mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator:latest";
public const string CosmosDbImage = "mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator:vnext-preview";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it necessary to use the preview version as a default? I know that this image is quite new but users can always:

new CosmosDbBuilder()
.WithImage("mcr.microsoft.com/cosmosdb/linux/azure-cosmos-emulator:vnext-preview")
.Build();

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The advantage of this PR is the use of this image as default, as it delivers significantly better results compared to the current :latest. Additionally, some configurations made in this PR are not compatible between the :latest and :vnext-preview versions. Currently, the :vnext-preview version shows considerably better results than :latest.


public const ushort CosmosDbPort = 8081;

Expand Down Expand Up @@ -44,6 +44,7 @@ protected override CosmosDbBuilder Init()
{
return base.Init()
.WithImage(CosmosDbImage)
.WithEnvironment("ENABLE_EXPLORER", "false")
.WithPortBinding(CosmosDbPort, true)
.WithWaitStrategy(Wait.ForUnixContainer().AddCustomWaitStrategy(new WaitUntil()));
}
Expand Down Expand Up @@ -73,25 +74,24 @@ private sealed class WaitUntil : IWaitUntil
public async Task<bool> UntilAsync(IContainer container)
{
// CosmosDB's preconfigured HTTP client will redirect the request to the container.
const string requestUri = "https://localhost/_explorer/emulator.pem";
const string REQUEST_URI = "http://localhost";

var httpClient = ((CosmosDbContainer)container).HttpClient;
using var httpClient = ((CosmosDbContainer)container).HttpClient;

try
{
using var httpResponse = await httpClient.GetAsync(requestUri)
using var httpResponse = await httpClient.GetAsync(REQUEST_URI)
.ConfigureAwait(false);

return httpResponse.IsSuccessStatusCode;
}
catch (Exception)
{
return false;
}
finally
{
httpClient.Dispose();
if (httpResponse.IsSuccessStatusCode)
{
await Task.Delay(2_000);
return true;
}
}
catch { }

return false;
}
}
}
}
8 changes: 4 additions & 4 deletions src/Testcontainers.CosmosDb/CosmosDbContainer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public CosmosDbContainer(CosmosDbConfiguration configuration)
public string GetConnectionString()
{
var properties = new Dictionary<string, string>();
properties.Add("AccountEndpoint", new UriBuilder(Uri.UriSchemeHttps, Hostname, GetMappedPublicPort(CosmosDbBuilder.CosmosDbPort)).ToString());
properties.Add("AccountEndpoint", new UriBuilder(Uri.UriSchemeHttp, Hostname, GetMappedPublicPort(CosmosDbBuilder.CosmosDbPort)).ToString());
properties.Add("AccountKey", CosmosDbBuilder.DefaultAccountKey);
return string.Join(";", properties.Select(property => string.Join("=", property.Key, property.Value)));
}
Expand Down Expand Up @@ -50,7 +50,7 @@ private sealed class UriRewriter : DelegatingHandler
/// <param name="hostname">The target hostname.</param>
/// <param name="port">The target port.</param>
public UriRewriter(string hostname, ushort port)
: base(new HttpClientHandler { ServerCertificateCustomValidationCallback = (_, _, _, _) => true })
: base(new HttpClientHandler())
{
_hostname = hostname;
_port = port;
Expand All @@ -59,8 +59,8 @@ public UriRewriter(string hostname, ushort port)
/// <inheritdoc />
protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
{
request.RequestUri = new UriBuilder(Uri.UriSchemeHttps, _hostname, _port, request.RequestUri.PathAndQuery).Uri;
request.RequestUri = new UriBuilder(Uri.UriSchemeHttp, _hostname, _port, request.RequestUri.PathAndQuery).Uri;
return base.SendAsync(request, cancellationToken);
}
}
}
}
2 changes: 1 addition & 1 deletion src/Testcontainers.CosmosDb/Testcontainers.CosmosDb.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,4 @@
<ItemGroup>
<ProjectReference Include="../Testcontainers/Testcontainers.csproj"/>
</ItemGroup>
</Project>
</Project>
74 changes: 62 additions & 12 deletions tests/Testcontainers.CosmosDb.Tests/CosmosDbContainerTest.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
namespace Testcontainers.CosmosDb;
using System;
using System.Linq;

namespace Testcontainers.CosmosDb.Tests;

public sealed class CosmosDbContainerTest : IAsyncLifetime
{
Expand All @@ -14,24 +17,71 @@ public Task DisposeAsync()
return _cosmosDbContainer.DisposeAsync().AsTask();
}

[Fact(Skip = "The Cosmos DB Linux Emulator Docker image does not run on Microsoft's CI environment (GitHub, Azure DevOps).")] // https://github.com/Azure/azure-cosmos-db-emulator-docker/issues/45.
[Fact]
[Trait(nameof(DockerCli.DockerPlatform), nameof(DockerCli.DockerPlatform.Linux))]
public async Task CreateDatabaseAndContainerSuccessful()
{
// Given
using var cosmosClient = new CosmosClient(
_cosmosDbContainer.GetConnectionString(),
new()
{
ConnectionMode = ConnectionMode.Gateway,
HttpClientFactory = () => _cosmosDbContainer.HttpClient
});


// When
var database = (await cosmosClient.CreateDatabaseIfNotExistsAsync("fakedb")).Database;
await database.CreateContainerIfNotExistsAsync("fakecontainer", "/id");
var databaseProperties = (await cosmosClient.GetDatabaseQueryIterator<DatabaseProperties>().ReadNextAsync()).First();


// Then
Assert.Equal("fakedb", databaseProperties.Id);
}


[Fact]
[Trait(nameof(DockerCli.DockerPlatform), nameof(DockerCli.DockerPlatform.Linux))]
public async Task AccountPropertiesIdReturnsLocalhost()
public async Task RetrieveItemCreated()
{
// Given
using var httpClient = _cosmosDbContainer.HttpClient;
using var cosmosClient = new CosmosClient(
_cosmosDbContainer.GetConnectionString(),
new()
{
ConnectionMode = ConnectionMode.Gateway,
HttpClientFactory = () => _cosmosDbContainer.HttpClient
});

var cosmosClientOptions = new CosmosClientOptions();
cosmosClientOptions.ConnectionMode = ConnectionMode.Gateway;
cosmosClientOptions.HttpClientFactory = () => httpClient;
var database = (await cosmosClient.CreateDatabaseIfNotExistsAsync("dbfake")).Database;
await database.CreateContainerIfNotExistsAsync("containerfake", "/id");
var container = database.GetContainer("containerfake");

var id = Guid.NewGuid().ToString();
var name = Guid.NewGuid().ToString();

using var cosmosClient = new CosmosClient(_cosmosDbContainer.GetConnectionString(), cosmosClientOptions);

// When
var accountProperties = await cosmosClient.ReadAccountAsync()
.ConfigureAwait(true);
var response = await container.CreateItemAsync(
new FakeItem { id = id, Name = name },
new PartitionKey(id));

var itemResponse = await container.ReadItemAsync<FakeItem>(
id,
new PartitionKey(id));


// Then
Assert.Equal("localhost", accountProperties.Id);
Assert.Equal(id, itemResponse.Resource.id);
Assert.Equal(name, itemResponse.Resource.Name);
}


private class FakeItem
{
public string id { get; set; }
public string Name { get; set; }
}
}
}