From 5a6127909e8d40dcd7293e79201175f9248f84c6 Mon Sep 17 00:00:00 2001 From: Shay Rojansky Date: Wed, 28 Feb 2024 15:29:37 +0100 Subject: [PATCH 1/3] Add Milvus test container --- Directory.Packages.props | 1 + Testcontainers.sln | 14 ++++ src/Testcontainers.Milvus/.editorconfig | 9 +++ src/Testcontainers.Milvus/MilvusBuilder.cs | 75 ++++++++++++++++++ .../MilvusConfiguration.cs | 56 +++++++++++++ src/Testcontainers.Milvus/MilvusContainer.cs | 12 +++ .../Testcontainers.Milvus.csproj | 14 ++++ src/Testcontainers.Milvus/Usings.cs | 8 ++ .../Testcontainers.Milvus.Tests/.editorconfig | 9 +++ .../MilvusContainerTests.cs | 78 +++++++++++++++++++ .../Testcontainers.Milvus.Tests.csproj | 20 +++++ 11 files changed, 296 insertions(+) create mode 100644 src/Testcontainers.Milvus/.editorconfig create mode 100644 src/Testcontainers.Milvus/MilvusBuilder.cs create mode 100644 src/Testcontainers.Milvus/MilvusConfiguration.cs create mode 100644 src/Testcontainers.Milvus/MilvusContainer.cs create mode 100644 src/Testcontainers.Milvus/Testcontainers.Milvus.csproj create mode 100644 src/Testcontainers.Milvus/Usings.cs create mode 100644 tests/Testcontainers.Milvus.Tests/.editorconfig create mode 100644 tests/Testcontainers.Milvus.Tests/MilvusContainerTests.cs create mode 100644 tests/Testcontainers.Milvus.Tests/Testcontainers.Milvus.Tests.csproj diff --git a/Directory.Packages.props b/Directory.Packages.props index 6eeb39533..3b7235616 100644 --- a/Directory.Packages.props +++ b/Directory.Packages.props @@ -47,6 +47,7 @@ + diff --git a/Testcontainers.sln b/Testcontainers.sln index 94af5e2c3..ed29623a5 100644 --- a/Testcontainers.sln +++ b/Testcontainers.sln @@ -191,6 +191,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.Tests", "tes EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.WebDriver.Tests", "tests\Testcontainers.WebDriver.Tests\Testcontainers.WebDriver.Tests.csproj", "{EBA72C3B-57D5-43FF-A5B4-3D55B3B6D4C2}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.Milvus", "src\Testcontainers.Milvus\Testcontainers.Milvus.csproj", "{B024E315-831F-429D-92AA-44B839AC10F4}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.Milvus.Tests", "tests\Testcontainers.Milvus.Tests\Testcontainers.Milvus.Tests.csproj", "{5247DF94-32F3-4ED6-AE71-6AB4F4078E6D}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -556,6 +560,14 @@ Global {EBA72C3B-57D5-43FF-A5B4-3D55B3B6D4C2}.Debug|Any CPU.Build.0 = Debug|Any CPU {EBA72C3B-57D5-43FF-A5B4-3D55B3B6D4C2}.Release|Any CPU.ActiveCfg = Release|Any CPU {EBA72C3B-57D5-43FF-A5B4-3D55B3B6D4C2}.Release|Any CPU.Build.0 = Release|Any CPU + {B024E315-831F-429D-92AA-44B839AC10F4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B024E315-831F-429D-92AA-44B839AC10F4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B024E315-831F-429D-92AA-44B839AC10F4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B024E315-831F-429D-92AA-44B839AC10F4}.Release|Any CPU.Build.0 = Release|Any CPU + {5247DF94-32F3-4ED6-AE71-6AB4F4078E6D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5247DF94-32F3-4ED6-AE71-6AB4F4078E6D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5247DF94-32F3-4ED6-AE71-6AB4F4078E6D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5247DF94-32F3-4ED6-AE71-6AB4F4078E6D}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(NestedProjects) = preSolution {5365F780-0E6C-41F0-B1B9-7DC34368F80C} = {673F23AE-7694-4BB9-ABD4-136D6C13634E} @@ -647,5 +659,7 @@ Global {1A1983E6-5297-435F-B467-E8E1F11277D6} = {7164F1FB-7F24-444A-ACD2-2C329C2B3CCF} {27CDB869-A150-4593-958F-6F26E5391E7C} = {7164F1FB-7F24-444A-ACD2-2C329C2B3CCF} {EBA72C3B-57D5-43FF-A5B4-3D55B3B6D4C2} = {7164F1FB-7F24-444A-ACD2-2C329C2B3CCF} + {B024E315-831F-429D-92AA-44B839AC10F4} = {673F23AE-7694-4BB9-ABD4-136D6C13634E} + {5247DF94-32F3-4ED6-AE71-6AB4F4078E6D} = {7164F1FB-7F24-444A-ACD2-2C329C2B3CCF} EndGlobalSection EndGlobal diff --git a/src/Testcontainers.Milvus/.editorconfig b/src/Testcontainers.Milvus/.editorconfig new file mode 100644 index 000000000..f8a7deb4a --- /dev/null +++ b/src/Testcontainers.Milvus/.editorconfig @@ -0,0 +1,9 @@ +root = true + +[*] +charset = utf-8 +indent_style = space +indent_size = 4 +insert_final_newline = true +trim_trailing_whitespace = true + diff --git a/src/Testcontainers.Milvus/MilvusBuilder.cs b/src/Testcontainers.Milvus/MilvusBuilder.cs new file mode 100644 index 000000000..51cdbadc2 --- /dev/null +++ b/src/Testcontainers.Milvus/MilvusBuilder.cs @@ -0,0 +1,75 @@ +namespace Testcontainers.Milvus; + +[PublicAPI] +public class MilvusBuilder : ContainerBuilder +{ + public const string MilvusImage = "milvusdb/milvus:v2.3.10"; + public const ushort MilvusGrpcPort = 19530; + public const ushort MilvusManagementPort = 9091; + + private string? _etcdEndpoint; + + public MilvusBuilder() : this(new MilvusConfiguration()) + => DockerResourceConfiguration = Init().DockerResourceConfiguration; + + private MilvusBuilder(MilvusConfiguration dockerResourceConfiguration) : base(dockerResourceConfiguration) + => DockerResourceConfiguration = dockerResourceConfiguration; + + public override MilvusContainer Build() + { + Validate(); + return new MilvusContainer(DockerResourceConfiguration, TestcontainersSettings.Logger); + } + + public MilvusBuilder WithEtcdEndpoint(string? etcdEndpoint) + { + _etcdEndpoint = etcdEndpoint; + return this; + } + + protected override MilvusBuilder Init() + { + var builder = base.Init() + .WithImage(MilvusImage) + .WithEnvironment("COMMON_STORAGETYPE", "local") + .WithCommand("milvus", "run", "standalone") + .WithPortBinding(MilvusGrpcPort, true) + .WithPortBinding(MilvusManagementPort, true) + .WithWaitStrategy( + Wait.ForUnixContainer() + .UntilHttpRequestIsSucceeded(h => h + .ForPort(MilvusManagementPort) + .ForPath("/healthz"))); + + if (_etcdEndpoint is null) + { + const string etcdYaml = """ + listen-client-urls: http://0.0.0.0:2379 + advertise-client-urls: http://0.0.0.0:2379 + """; + + builder = builder + .WithResourceMapping(Encoding.UTF8.GetBytes(etcdYaml), "/milvus/configs/embedEtcd.yaml") + .WithEnvironment("ETCD_USE_EMBED", "true") + .WithEnvironment("ETCD_DATA_DIR", "/var/lib/milvus/etcd") + .WithEnvironment("ETCD_CONFIG_PATH", "/milvus/configs/embedEtcd.yaml"); + } + else + { + throw new NotImplementedException(); + } + + return builder; + } + + protected override MilvusBuilder Clone(IResourceConfiguration resourceConfiguration) + => Merge(DockerResourceConfiguration, new MilvusConfiguration(resourceConfiguration)); + + protected override MilvusBuilder Merge(MilvusConfiguration oldValue, MilvusConfiguration newValue) + => new(new MilvusConfiguration(oldValue, newValue)); + + protected override MilvusConfiguration DockerResourceConfiguration { get; } + + protected override MilvusBuilder Clone(IContainerConfiguration resourceConfiguration) + => Merge(DockerResourceConfiguration, new MilvusConfiguration(resourceConfiguration)); +} diff --git a/src/Testcontainers.Milvus/MilvusConfiguration.cs b/src/Testcontainers.Milvus/MilvusConfiguration.cs new file mode 100644 index 000000000..2bc3b0cc6 --- /dev/null +++ b/src/Testcontainers.Milvus/MilvusConfiguration.cs @@ -0,0 +1,56 @@ +namespace Testcontainers.Milvus; + +public sealed class MilvusConfiguration : ContainerConfiguration +{ + + /// + /// Initializes a new instance of the class. + /// + public MilvusConfiguration() + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The Docker resource configuration. + public MilvusConfiguration(IResourceConfiguration resourceConfiguration) + : base(resourceConfiguration) + { + } + + /// + /// Initializes a new instance of the class. + /// + /// The Docker resource configuration. + public MilvusConfiguration(IContainerConfiguration resourceConfiguration) + : base(resourceConfiguration) + { + // Passes the configuration upwards to the base implementations to create an updated immutable copy. + } + + /// + /// Initializes a new instance of the class. + /// + /// The Docker resource configuration. + public MilvusConfiguration(MilvusConfiguration resourceConfiguration) + : this(new MilvusConfiguration(), resourceConfiguration) + { + // Passes the configuration upwards to the base implementations to create an updated immutable copy. + } + + /// + /// Initializes a new instance of the class. + /// + /// The old Docker resource configuration. + /// The new Docker resource configuration. + public MilvusConfiguration(MilvusConfiguration oldValue, MilvusConfiguration newValue) + : base(oldValue, newValue) + { + } + + /// + /// An optional endpoint for an external etcd service. If null, uses an embedded etcd service. + /// + public string? EtcdEndpoint { get; } +} diff --git a/src/Testcontainers.Milvus/MilvusContainer.cs b/src/Testcontainers.Milvus/MilvusContainer.cs new file mode 100644 index 000000000..1acbb846d --- /dev/null +++ b/src/Testcontainers.Milvus/MilvusContainer.cs @@ -0,0 +1,12 @@ +namespace Testcontainers.Milvus; + +public class MilvusContainer(MilvusConfiguration configuration, ILogger logger) + : DockerContainer(configuration, logger) +{ + /// + /// Gets the Milvus endpoint. + /// + /// The Milvus endpoint. + public Uri GetEndpoint() + => new Uri($"http://{Hostname}:{GetMappedPublicPort(MilvusBuilder.MilvusGrpcPort)}"); +} diff --git a/src/Testcontainers.Milvus/Testcontainers.Milvus.csproj b/src/Testcontainers.Milvus/Testcontainers.Milvus.csproj new file mode 100644 index 000000000..904198fb2 --- /dev/null +++ b/src/Testcontainers.Milvus/Testcontainers.Milvus.csproj @@ -0,0 +1,14 @@ + + + net6.0;netstandard2.0;net462 + latest + enable + enable + + + + + + + + diff --git a/src/Testcontainers.Milvus/Usings.cs b/src/Testcontainers.Milvus/Usings.cs new file mode 100644 index 000000000..23960986a --- /dev/null +++ b/src/Testcontainers.Milvus/Usings.cs @@ -0,0 +1,8 @@ +global using System; +global using System.Text; +global using Docker.DotNet.Models; +global using DotNet.Testcontainers.Builders; +global using DotNet.Testcontainers.Configurations; +global using DotNet.Testcontainers.Containers; +global using JetBrains.Annotations; +global using Microsoft.Extensions.Logging; diff --git a/tests/Testcontainers.Milvus.Tests/.editorconfig b/tests/Testcontainers.Milvus.Tests/.editorconfig new file mode 100644 index 000000000..f8a7deb4a --- /dev/null +++ b/tests/Testcontainers.Milvus.Tests/.editorconfig @@ -0,0 +1,9 @@ +root = true + +[*] +charset = utf-8 +indent_style = space +indent_size = 4 +insert_final_newline = true +trim_trailing_whitespace = true + diff --git a/tests/Testcontainers.Milvus.Tests/MilvusContainerTests.cs b/tests/Testcontainers.Milvus.Tests/MilvusContainerTests.cs new file mode 100644 index 000000000..a3b8539bc --- /dev/null +++ b/tests/Testcontainers.Milvus.Tests/MilvusContainerTests.cs @@ -0,0 +1,78 @@ +using Docker.DotNet.Models; +using DotNet.Testcontainers.Builders; +using DotNet.Testcontainers.Commons; +using DotNet.Testcontainers.Containers; +using Milvus.Client; +using Xunit; + +namespace Testcontainers.Milvus.Tests; + +public class MilvusContainerTests +{ + [Fact] + [Trait(nameof(DockerCli.DockerPlatform), nameof(DockerCli.DockerPlatform.Linux))] + public async Task WithDefaultConfig() + { + var container = new MilvusBuilder() + .WithImage("milvusdb/milvus:v2.3.10") + .Build(); + + try + { + await container.StartAsync(); + + var client = new MilvusClient(container.GetEndpoint()); + var version = await client.GetVersionAsync(); + + Assert.Equal("v2.3.10", version); + } + finally + { + await container.StopAsync(); + } + } + + [Fact] + [Trait(nameof(DockerCli.DockerPlatform), nameof(DockerCli.DockerPlatform.Linux))] + public async Task WithExternalEtcd() + { + var network = new NetworkBuilder().Build(); + var etcdContainer = new ContainerBuilder() + .WithImage("quay.io/coreos/etcd:v3.5.5") + .WithNetwork(network) + .WithNetworkAliases("etcd") + .WithCommand( + "etcd", + "-advertise-client-urls=http://127.0.0.1:2379", + "-listen-client-urls=http://0.0.0.0:2379", + "--data-dir=/etcd") + .WithEnvironment("ETCD_AUTO_COMPACTION_MODE", "revision") + .WithEnvironment("ETCD_AUTO_COMPACTION_RETENTION", "1000") + .WithEnvironment("ETCD_QUOTA_BACKEND_BYTES", "4294967296") + .WithEnvironment("ETCD_SNAPSHOT_COUNT", "50000") + .WithWaitStrategy(Wait.ForUnixContainer().UntilMessageIsLogged(".*ready to serve client requests.*")) + .Build(); + + var milvusContainer = new MilvusBuilder() + .WithImage("milvusdb/milvus:v2.3.10") + .WithNetwork(network) + .WithEtcdEndpoint("etcd:2379") + .DependsOn(etcdContainer) + .Build(); + + await milvusContainer.StartAsync(); + + try + { + + var client = new MilvusClient(milvusContainer.GetEndpoint()); + var version = await client.GetVersionAsync(); + + Assert.Equal("v2.3.10", version); + } + finally + { + await milvusContainer.StopAsync(); + } + } +} diff --git a/tests/Testcontainers.Milvus.Tests/Testcontainers.Milvus.Tests.csproj b/tests/Testcontainers.Milvus.Tests/Testcontainers.Milvus.Tests.csproj new file mode 100644 index 000000000..1ea90e495 --- /dev/null +++ b/tests/Testcontainers.Milvus.Tests/Testcontainers.Milvus.Tests.csproj @@ -0,0 +1,20 @@ + + + net8.0 + false + false + enable + enable + + + + + + + + + + + + + From 3db28477cf0b60a393f95d0c6601243298f94dc9 Mon Sep 17 00:00:00 2001 From: Shay Rojansky Date: Wed, 28 Feb 2024 18:41:35 +0100 Subject: [PATCH 2/3] Fix external etcd config --- src/Testcontainers.Milvus/MilvusBuilder.cs | 38 +++++++++------------- 1 file changed, 15 insertions(+), 23 deletions(-) diff --git a/src/Testcontainers.Milvus/MilvusBuilder.cs b/src/Testcontainers.Milvus/MilvusBuilder.cs index 51cdbadc2..3e685a1e9 100644 --- a/src/Testcontainers.Milvus/MilvusBuilder.cs +++ b/src/Testcontainers.Milvus/MilvusBuilder.cs @@ -7,8 +7,6 @@ public class MilvusBuilder : ContainerBuilder DockerResourceConfiguration = Init().DockerResourceConfiguration; @@ -22,13 +20,18 @@ public override MilvusContainer Build() } public MilvusBuilder WithEtcdEndpoint(string? etcdEndpoint) - { - _etcdEndpoint = etcdEndpoint; - return this; - } + => WithEnvironment("ETCD_USE_EMBED", "false") + .WithEnvironment("ETCD_DATA_DIR", "") + .WithEnvironment("ETCD_CONFIG_PATH", "") + .WithEnvironment("ETCD_ENDPOINTS", etcdEndpoint); protected override MilvusBuilder Init() { + const string etcdYaml = """ + listen-client-urls: http://0.0.0.0:2379 + advertise-client-urls: http://0.0.0.0:2379 + """; + var builder = base.Init() .WithImage(MilvusImage) .WithEnvironment("COMMON_STORAGETYPE", "local") @@ -41,23 +44,12 @@ protected override MilvusBuilder Init() .ForPort(MilvusManagementPort) .ForPath("/healthz"))); - if (_etcdEndpoint is null) - { - const string etcdYaml = """ - listen-client-urls: http://0.0.0.0:2379 - advertise-client-urls: http://0.0.0.0:2379 - """; - - builder = builder - .WithResourceMapping(Encoding.UTF8.GetBytes(etcdYaml), "/milvus/configs/embedEtcd.yaml") - .WithEnvironment("ETCD_USE_EMBED", "true") - .WithEnvironment("ETCD_DATA_DIR", "/var/lib/milvus/etcd") - .WithEnvironment("ETCD_CONFIG_PATH", "/milvus/configs/embedEtcd.yaml"); - } - else - { - throw new NotImplementedException(); - } + // For embedded etcd only; see WithEtcdEndpoint for using an external etcd. + builder = builder + .WithEnvironment("ETCD_USE_EMBED", "true") + .WithEnvironment("ETCD_DATA_DIR", "/var/lib/milvus/etcd") + .WithEnvironment("ETCD_CONFIG_PATH", "/milvus/configs/embedEtcd.yaml") + .WithResourceMapping(Encoding.UTF8.GetBytes(etcdYaml), "/milvus/configs/embedEtcd.yaml"); return builder; } From 016d61a1ca160cabb99074ceb927dde2cc76844a Mon Sep 17 00:00:00 2001 From: Andre Hofmeister <9199345+HofmeisterAn@users.noreply.github.com> Date: Thu, 29 Feb 2024 19:52:29 +0100 Subject: [PATCH 3/3] chore: Align Milvus module --- Testcontainers.sln | 28 ++--- src/Testcontainers.Milvus/.editorconfig | 10 +- src/Testcontainers.Milvus/MilvusBuilder.cs | 109 +++++++++++------- .../MilvusConfiguration.cs | 11 +- src/Testcontainers.Milvus/MilvusContainer.cs | 21 +++- .../Testcontainers.Milvus.csproj | 8 +- src/Testcontainers.Milvus/Usings.cs | 2 +- .../Testcontainers.Milvus.Tests/.editorconfig | 8 -- .../MilvusContainerTest.cs | 79 +++++++++++++ .../MilvusContainerTests.cs | 78 ------------- .../Testcontainers.Milvus.Tests.csproj | 8 +- tests/Testcontainers.Milvus.Tests/Usings.cs | 7 ++ 12 files changed, 197 insertions(+), 172 deletions(-) create mode 100644 tests/Testcontainers.Milvus.Tests/MilvusContainerTest.cs delete mode 100644 tests/Testcontainers.Milvus.Tests/MilvusContainerTests.cs create mode 100644 tests/Testcontainers.Milvus.Tests/Usings.cs diff --git a/Testcontainers.sln b/Testcontainers.sln index ed29623a5..9595905ed 100644 --- a/Testcontainers.sln +++ b/Testcontainers.sln @@ -63,6 +63,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.LocalStack", EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.MariaDb", "src\Testcontainers.MariaDb\Testcontainers.MariaDb.csproj", "{4B204EB3-C478-422E-9B6F-62DF3871291A}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.Milvus", "src\Testcontainers.Milvus\Testcontainers.Milvus.csproj", "{B024E315-831F-429D-92AA-44B839AC10F4}" +EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.Minio", "src\Testcontainers.Minio\Testcontainers.Minio.csproj", "{1266E1E6-5CEF-4161-8B45-83282455746E}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.MongoDb", "src\Testcontainers.MongoDb\Testcontainers.MongoDb.csproj", "{2613F146-6C66-4059-9D37-D48BA6B61515}" @@ -151,6 +153,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.LocalStack.T EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.MariaDb.Tests", "tests\Testcontainers.MariaDb.Tests\Testcontainers.MariaDb.Tests.csproj", "{7F0AE083-9DB8-4BD4-91F7-C199DCC7301D}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.Milvus.Tests", "tests\Testcontainers.Milvus.Tests\Testcontainers.Milvus.Tests.csproj", "{5247DF94-32F3-4ED6-AE71-6AB4F4078E6D}" +EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.Minio.Tests", "tests\Testcontainers.Minio.Tests\Testcontainers.Minio.Tests.csproj", "{5DB1F35F-B714-4B62-84BE-16A33084D3E1}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.MongoDb.Tests", "tests\Testcontainers.MongoDb.Tests\Testcontainers.MongoDb.Tests.csproj", "{82A7E7B8-3187-4CAE-845B-0BF43409B38A}" @@ -191,10 +195,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.Tests", "tes EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.WebDriver.Tests", "tests\Testcontainers.WebDriver.Tests\Testcontainers.WebDriver.Tests.csproj", "{EBA72C3B-57D5-43FF-A5B4-3D55B3B6D4C2}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.Milvus", "src\Testcontainers.Milvus\Testcontainers.Milvus.csproj", "{B024E315-831F-429D-92AA-44B839AC10F4}" -EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.Milvus.Tests", "tests\Testcontainers.Milvus.Tests\Testcontainers.Milvus.Tests.csproj", "{5247DF94-32F3-4ED6-AE71-6AB4F4078E6D}" -EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -304,6 +304,10 @@ Global {4B204EB3-C478-422E-9B6F-62DF3871291A}.Debug|Any CPU.Build.0 = Debug|Any CPU {4B204EB3-C478-422E-9B6F-62DF3871291A}.Release|Any CPU.ActiveCfg = Release|Any CPU {4B204EB3-C478-422E-9B6F-62DF3871291A}.Release|Any CPU.Build.0 = Release|Any CPU + {B024E315-831F-429D-92AA-44B839AC10F4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B024E315-831F-429D-92AA-44B839AC10F4}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B024E315-831F-429D-92AA-44B839AC10F4}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B024E315-831F-429D-92AA-44B839AC10F4}.Release|Any CPU.Build.0 = Release|Any CPU {1266E1E6-5CEF-4161-8B45-83282455746E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {1266E1E6-5CEF-4161-8B45-83282455746E}.Debug|Any CPU.Build.0 = Debug|Any CPU {1266E1E6-5CEF-4161-8B45-83282455746E}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -480,6 +484,10 @@ Global {7F0AE083-9DB8-4BD4-91F7-C199DCC7301D}.Debug|Any CPU.Build.0 = Debug|Any CPU {7F0AE083-9DB8-4BD4-91F7-C199DCC7301D}.Release|Any CPU.ActiveCfg = Release|Any CPU {7F0AE083-9DB8-4BD4-91F7-C199DCC7301D}.Release|Any CPU.Build.0 = Release|Any CPU + {5247DF94-32F3-4ED6-AE71-6AB4F4078E6D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {5247DF94-32F3-4ED6-AE71-6AB4F4078E6D}.Debug|Any CPU.Build.0 = Debug|Any CPU + {5247DF94-32F3-4ED6-AE71-6AB4F4078E6D}.Release|Any CPU.ActiveCfg = Release|Any CPU + {5247DF94-32F3-4ED6-AE71-6AB4F4078E6D}.Release|Any CPU.Build.0 = Release|Any CPU {5DB1F35F-B714-4B62-84BE-16A33084D3E1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {5DB1F35F-B714-4B62-84BE-16A33084D3E1}.Debug|Any CPU.Build.0 = Debug|Any CPU {5DB1F35F-B714-4B62-84BE-16A33084D3E1}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -560,14 +568,6 @@ Global {EBA72C3B-57D5-43FF-A5B4-3D55B3B6D4C2}.Debug|Any CPU.Build.0 = Debug|Any CPU {EBA72C3B-57D5-43FF-A5B4-3D55B3B6D4C2}.Release|Any CPU.ActiveCfg = Release|Any CPU {EBA72C3B-57D5-43FF-A5B4-3D55B3B6D4C2}.Release|Any CPU.Build.0 = Release|Any CPU - {B024E315-831F-429D-92AA-44B839AC10F4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B024E315-831F-429D-92AA-44B839AC10F4}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B024E315-831F-429D-92AA-44B839AC10F4}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B024E315-831F-429D-92AA-44B839AC10F4}.Release|Any CPU.Build.0 = Release|Any CPU - {5247DF94-32F3-4ED6-AE71-6AB4F4078E6D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {5247DF94-32F3-4ED6-AE71-6AB4F4078E6D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {5247DF94-32F3-4ED6-AE71-6AB4F4078E6D}.Release|Any CPU.ActiveCfg = Release|Any CPU - {5247DF94-32F3-4ED6-AE71-6AB4F4078E6D}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(NestedProjects) = preSolution {5365F780-0E6C-41F0-B1B9-7DC34368F80C} = {673F23AE-7694-4BB9-ABD4-136D6C13634E} @@ -595,6 +595,7 @@ Global {FCF59758-2403-4EC9-9EAE-4EC69A3F27AF} = {673F23AE-7694-4BB9-ABD4-136D6C13634E} {3792268A-EF08-4569-8118-991E08FD61C4} = {673F23AE-7694-4BB9-ABD4-136D6C13634E} {4B204EB3-C478-422E-9B6F-62DF3871291A} = {673F23AE-7694-4BB9-ABD4-136D6C13634E} + {B024E315-831F-429D-92AA-44B839AC10F4} = {673F23AE-7694-4BB9-ABD4-136D6C13634E} {1266E1E6-5CEF-4161-8B45-83282455746E} = {673F23AE-7694-4BB9-ABD4-136D6C13634E} {2613F146-6C66-4059-9D37-D48BA6B61515} = {673F23AE-7694-4BB9-ABD4-136D6C13634E} {121FB123-40D9-44D4-9AB7-AD57ED34F466} = {673F23AE-7694-4BB9-ABD4-136D6C13634E} @@ -639,6 +640,7 @@ Global {FA59D75A-8D3A-412C-92E6-4A56033162DD} = {7164F1FB-7F24-444A-ACD2-2C329C2B3CCF} {728CBE16-1D52-4F84-AF01-7229E6013512} = {7164F1FB-7F24-444A-ACD2-2C329C2B3CCF} {7F0AE083-9DB8-4BD4-91F7-C199DCC7301D} = {7164F1FB-7F24-444A-ACD2-2C329C2B3CCF} + {5247DF94-32F3-4ED6-AE71-6AB4F4078E6D} = {7164F1FB-7F24-444A-ACD2-2C329C2B3CCF} {5DB1F35F-B714-4B62-84BE-16A33084D3E1} = {7164F1FB-7F24-444A-ACD2-2C329C2B3CCF} {82A7E7B8-3187-4CAE-845B-0BF43409B38A} = {7164F1FB-7F24-444A-ACD2-2C329C2B3CCF} {25DBED78-99F4-433F-BBF5-1B4E9DEAE437} = {7164F1FB-7F24-444A-ACD2-2C329C2B3CCF} @@ -659,7 +661,5 @@ Global {1A1983E6-5297-435F-B467-E8E1F11277D6} = {7164F1FB-7F24-444A-ACD2-2C329C2B3CCF} {27CDB869-A150-4593-958F-6F26E5391E7C} = {7164F1FB-7F24-444A-ACD2-2C329C2B3CCF} {EBA72C3B-57D5-43FF-A5B4-3D55B3B6D4C2} = {7164F1FB-7F24-444A-ACD2-2C329C2B3CCF} - {B024E315-831F-429D-92AA-44B839AC10F4} = {673F23AE-7694-4BB9-ABD4-136D6C13634E} - {5247DF94-32F3-4ED6-AE71-6AB4F4078E6D} = {7164F1FB-7F24-444A-ACD2-2C329C2B3CCF} EndGlobalSection EndGlobal diff --git a/src/Testcontainers.Milvus/.editorconfig b/src/Testcontainers.Milvus/.editorconfig index f8a7deb4a..6f066619d 100644 --- a/src/Testcontainers.Milvus/.editorconfig +++ b/src/Testcontainers.Milvus/.editorconfig @@ -1,9 +1 @@ -root = true - -[*] -charset = utf-8 -indent_style = space -indent_size = 4 -insert_final_newline = true -trim_trailing_whitespace = true - +root = true \ No newline at end of file diff --git a/src/Testcontainers.Milvus/MilvusBuilder.cs b/src/Testcontainers.Milvus/MilvusBuilder.cs index 3e685a1e9..24c6ed318 100644 --- a/src/Testcontainers.Milvus/MilvusBuilder.cs +++ b/src/Testcontainers.Milvus/MilvusBuilder.cs @@ -1,67 +1,94 @@ namespace Testcontainers.Milvus; +/// [PublicAPI] -public class MilvusBuilder : ContainerBuilder +public sealed class MilvusBuilder : ContainerBuilder { + public const string MilvusEtcdConfigFilePath = "/milvus/configs/embedEtcd.yaml"; + public const string MilvusImage = "milvusdb/milvus:v2.3.10"; - public const ushort MilvusGrpcPort = 19530; + public const ushort MilvusManagementPort = 9091; - public MilvusBuilder() : this(new MilvusConfiguration()) - => DockerResourceConfiguration = Init().DockerResourceConfiguration; + public const ushort MilvusGrpcPort = 19530; + + private static readonly byte[] EtcdConfig = Encoding.Default.GetBytes(string.Join("\n", "advertise-client-urls: http://0.0.0.0:2379", "listen-client-urls: http://0.0.0.0:2379")); + + /// + /// Initializes a new instance of the class. + /// + public MilvusBuilder() + : this(new MilvusConfiguration()) + { + DockerResourceConfiguration = Init().DockerResourceConfiguration; + } + + /// + /// Initializes a new instance of the class. + /// + /// The Docker resource configuration. + private MilvusBuilder(MilvusConfiguration resourceConfiguration) + : base(resourceConfiguration) + { + DockerResourceConfiguration = resourceConfiguration; + } + + /// + protected override MilvusConfiguration DockerResourceConfiguration { get; } - private MilvusBuilder(MilvusConfiguration dockerResourceConfiguration) : base(dockerResourceConfiguration) - => DockerResourceConfiguration = dockerResourceConfiguration; + /// + /// Sets the etcd endpoint. + /// + /// The etcd endpoint. + /// A configured instance of . + public MilvusBuilder WithEtcdEndpoint(string etcdEndpoint) + { + return WithEnvironment("ETCD_USE_EMBED", "false") + .WithEnvironment("ETCD_CONFIG_PATH", string.Empty) + .WithEnvironment("ETCD_DATA_DIR", string.Empty) + .WithEnvironment("ETCD_ENDPOINTS", etcdEndpoint); + } + /// public override MilvusContainer Build() { Validate(); return new MilvusContainer(DockerResourceConfiguration, TestcontainersSettings.Logger); } - public MilvusBuilder WithEtcdEndpoint(string? etcdEndpoint) - => WithEnvironment("ETCD_USE_EMBED", "false") - .WithEnvironment("ETCD_DATA_DIR", "") - .WithEnvironment("ETCD_CONFIG_PATH", "") - .WithEnvironment("ETCD_ENDPOINTS", etcdEndpoint); - + /// protected override MilvusBuilder Init() { - const string etcdYaml = """ - listen-client-urls: http://0.0.0.0:2379 - advertise-client-urls: http://0.0.0.0:2379 - """; - - var builder = base.Init() + return base.Init() .WithImage(MilvusImage) - .WithEnvironment("COMMON_STORAGETYPE", "local") - .WithCommand("milvus", "run", "standalone") - .WithPortBinding(MilvusGrpcPort, true) .WithPortBinding(MilvusManagementPort, true) - .WithWaitStrategy( - Wait.ForUnixContainer() - .UntilHttpRequestIsSucceeded(h => h - .ForPort(MilvusManagementPort) - .ForPath("/healthz"))); - - // For embedded etcd only; see WithEtcdEndpoint for using an external etcd. - builder = builder + .WithPortBinding(MilvusGrpcPort, true) + .WithCommand("milvus", "run", "standalone") + .WithEnvironment("COMMON_STORAGETYPE", "local") + // For embedded etcd only; see WithEtcdEndpoint(string) for using an external etcd. .WithEnvironment("ETCD_USE_EMBED", "true") + .WithEnvironment("ETCD_CONFIG_PATH", MilvusEtcdConfigFilePath) .WithEnvironment("ETCD_DATA_DIR", "/var/lib/milvus/etcd") - .WithEnvironment("ETCD_CONFIG_PATH", "/milvus/configs/embedEtcd.yaml") - .WithResourceMapping(Encoding.UTF8.GetBytes(etcdYaml), "/milvus/configs/embedEtcd.yaml"); - - return builder; + .WithResourceMapping(EtcdConfig, MilvusEtcdConfigFilePath) + .WithWaitStrategy(Wait.ForUnixContainer().UntilHttpRequestIsSucceeded(request => + request.ForPort(MilvusManagementPort).ForPath("/healthz"))); } + /// protected override MilvusBuilder Clone(IResourceConfiguration resourceConfiguration) - => Merge(DockerResourceConfiguration, new MilvusConfiguration(resourceConfiguration)); - - protected override MilvusBuilder Merge(MilvusConfiguration oldValue, MilvusConfiguration newValue) - => new(new MilvusConfiguration(oldValue, newValue)); - - protected override MilvusConfiguration DockerResourceConfiguration { get; } + { + return Merge(DockerResourceConfiguration, new MilvusConfiguration(resourceConfiguration)); + } + /// protected override MilvusBuilder Clone(IContainerConfiguration resourceConfiguration) - => Merge(DockerResourceConfiguration, new MilvusConfiguration(resourceConfiguration)); -} + { + return Merge(DockerResourceConfiguration, new MilvusConfiguration(resourceConfiguration)); + } + + /// + protected override MilvusBuilder Merge(MilvusConfiguration oldValue, MilvusConfiguration newValue) + { + return new MilvusBuilder(new MilvusConfiguration(oldValue, newValue)); + } +} \ No newline at end of file diff --git a/src/Testcontainers.Milvus/MilvusConfiguration.cs b/src/Testcontainers.Milvus/MilvusConfiguration.cs index 2bc3b0cc6..32b7dba70 100644 --- a/src/Testcontainers.Milvus/MilvusConfiguration.cs +++ b/src/Testcontainers.Milvus/MilvusConfiguration.cs @@ -1,8 +1,9 @@ namespace Testcontainers.Milvus; +/// +[PublicAPI] public sealed class MilvusConfiguration : ContainerConfiguration { - /// /// Initializes a new instance of the class. /// @@ -17,6 +18,7 @@ public MilvusConfiguration() public MilvusConfiguration(IResourceConfiguration resourceConfiguration) : base(resourceConfiguration) { + // Passes the configuration upwards to the base implementations to create an updated immutable copy. } /// @@ -48,9 +50,4 @@ public MilvusConfiguration(MilvusConfiguration oldValue, MilvusConfiguration new : base(oldValue, newValue) { } - - /// - /// An optional endpoint for an external etcd service. If null, uses an embedded etcd service. - /// - public string? EtcdEndpoint { get; } -} +} \ No newline at end of file diff --git a/src/Testcontainers.Milvus/MilvusContainer.cs b/src/Testcontainers.Milvus/MilvusContainer.cs index 1acbb846d..87c58f855 100644 --- a/src/Testcontainers.Milvus/MilvusContainer.cs +++ b/src/Testcontainers.Milvus/MilvusContainer.cs @@ -1,12 +1,25 @@ namespace Testcontainers.Milvus; -public class MilvusContainer(MilvusConfiguration configuration, ILogger logger) - : DockerContainer(configuration, logger) +/// +[PublicAPI] +public sealed class MilvusContainer : DockerContainer { + /// + /// Initializes a new instance of the class. + /// + /// The container configuration. + /// The logger. + public MilvusContainer(MilvusConfiguration configuration, ILogger logger) + : base(configuration, logger) + { + } + /// /// Gets the Milvus endpoint. /// /// The Milvus endpoint. public Uri GetEndpoint() - => new Uri($"http://{Hostname}:{GetMappedPublicPort(MilvusBuilder.MilvusGrpcPort)}"); -} + { + return new UriBuilder(Uri.UriSchemeHttp, Hostname, GetMappedPublicPort(MilvusBuilder.MilvusGrpcPort)).Uri; + } +} \ No newline at end of file diff --git a/src/Testcontainers.Milvus/Testcontainers.Milvus.csproj b/src/Testcontainers.Milvus/Testcontainers.Milvus.csproj index 904198fb2..51735310a 100644 --- a/src/Testcontainers.Milvus/Testcontainers.Milvus.csproj +++ b/src/Testcontainers.Milvus/Testcontainers.Milvus.csproj @@ -1,9 +1,7 @@ - + - net6.0;netstandard2.0;net462 + net6.0;net8.0;netstandard2.0;netstandard2.1;net462 latest - enable - enable @@ -11,4 +9,4 @@ - + \ No newline at end of file diff --git a/src/Testcontainers.Milvus/Usings.cs b/src/Testcontainers.Milvus/Usings.cs index 23960986a..fd93092b4 100644 --- a/src/Testcontainers.Milvus/Usings.cs +++ b/src/Testcontainers.Milvus/Usings.cs @@ -5,4 +5,4 @@ global using DotNet.Testcontainers.Configurations; global using DotNet.Testcontainers.Containers; global using JetBrains.Annotations; -global using Microsoft.Extensions.Logging; +global using Microsoft.Extensions.Logging; \ No newline at end of file diff --git a/tests/Testcontainers.Milvus.Tests/.editorconfig b/tests/Testcontainers.Milvus.Tests/.editorconfig index f8a7deb4a..78b36ca08 100644 --- a/tests/Testcontainers.Milvus.Tests/.editorconfig +++ b/tests/Testcontainers.Milvus.Tests/.editorconfig @@ -1,9 +1 @@ root = true - -[*] -charset = utf-8 -indent_style = space -indent_size = 4 -insert_final_newline = true -trim_trailing_whitespace = true - diff --git a/tests/Testcontainers.Milvus.Tests/MilvusContainerTest.cs b/tests/Testcontainers.Milvus.Tests/MilvusContainerTest.cs new file mode 100644 index 000000000..b41c488bf --- /dev/null +++ b/tests/Testcontainers.Milvus.Tests/MilvusContainerTest.cs @@ -0,0 +1,79 @@ +namespace Testcontainers.Milvus; + +public abstract class MilvusContainerTest : IAsyncLifetime +{ + private const string MilvusVersion = "v2.3.10"; + + private readonly MilvusContainer _milvusContainer; + + private MilvusContainerTest(MilvusContainer milvusContainer) + { + _milvusContainer = milvusContainer; + } + + public Task InitializeAsync() + { + return _milvusContainer.StartAsync(); + } + + public Task DisposeAsync() + { + return _milvusContainer.DisposeAsync().AsTask(); + } + + [Fact] + [Trait(nameof(DockerCli.DockerPlatform), nameof(DockerCli.DockerPlatform.Linux))] + public async Task GetVersionReturnsExpectedVersion() + { + // Given + using var client = new MilvusClient(_milvusContainer.GetEndpoint()); + + // When + var version = await client.GetVersionAsync() + .ConfigureAwait(true); + + // Then + Assert.Equal(MilvusVersion, version); + } + + [UsedImplicitly] + public sealed class MilvusDefaultConfiguration : MilvusContainerTest + { + public MilvusDefaultConfiguration() + : base(new MilvusBuilder().WithImage("milvusdb/milvus:" + MilvusVersion).Build()) + { + } + } + + [UsedImplicitly] + public sealed class MilvusSidecarConfiguration : MilvusContainerTest + { + public MilvusSidecarConfiguration() + : this(new NetworkBuilder().Build()) + { + } + + private MilvusSidecarConfiguration(INetwork network) + : base(new MilvusBuilder() + .WithImage("milvusdb/milvus:" + MilvusVersion) + .WithEtcdEndpoint("etcd:2379") + .DependsOn(new ContainerBuilder() + .WithImage("quay.io/coreos/etcd:v3.5.5") + .WithNetworkAliases("etcd") + .WithCommand("etcd") + .WithCommand("-advertise-client-urls=http://127.0.0.1:2379") + .WithCommand("-listen-client-urls=http://0.0.0.0:2379") + .WithCommand("-data-dir=/etcd") + .WithEnvironment("ETCD_AUTO_COMPACTION_MODE", "periodic") + .WithEnvironment("ETCD_AUTO_COMPACTION_RETENTION", "0") + .WithEnvironment("ETCD_QUOTA_BACKEND_BYTES", "0") + .WithEnvironment("ETCD_SNAPSHOT_COUNT", "100000") + .WithWaitStrategy(Wait.ForUnixContainer().UntilMessageIsLogged("ready to serve client requests")) + .DependsOn(network) + .Build()) + .DependsOn(network) + .Build()) + { + } + } +} \ No newline at end of file diff --git a/tests/Testcontainers.Milvus.Tests/MilvusContainerTests.cs b/tests/Testcontainers.Milvus.Tests/MilvusContainerTests.cs deleted file mode 100644 index a3b8539bc..000000000 --- a/tests/Testcontainers.Milvus.Tests/MilvusContainerTests.cs +++ /dev/null @@ -1,78 +0,0 @@ -using Docker.DotNet.Models; -using DotNet.Testcontainers.Builders; -using DotNet.Testcontainers.Commons; -using DotNet.Testcontainers.Containers; -using Milvus.Client; -using Xunit; - -namespace Testcontainers.Milvus.Tests; - -public class MilvusContainerTests -{ - [Fact] - [Trait(nameof(DockerCli.DockerPlatform), nameof(DockerCli.DockerPlatform.Linux))] - public async Task WithDefaultConfig() - { - var container = new MilvusBuilder() - .WithImage("milvusdb/milvus:v2.3.10") - .Build(); - - try - { - await container.StartAsync(); - - var client = new MilvusClient(container.GetEndpoint()); - var version = await client.GetVersionAsync(); - - Assert.Equal("v2.3.10", version); - } - finally - { - await container.StopAsync(); - } - } - - [Fact] - [Trait(nameof(DockerCli.DockerPlatform), nameof(DockerCli.DockerPlatform.Linux))] - public async Task WithExternalEtcd() - { - var network = new NetworkBuilder().Build(); - var etcdContainer = new ContainerBuilder() - .WithImage("quay.io/coreos/etcd:v3.5.5") - .WithNetwork(network) - .WithNetworkAliases("etcd") - .WithCommand( - "etcd", - "-advertise-client-urls=http://127.0.0.1:2379", - "-listen-client-urls=http://0.0.0.0:2379", - "--data-dir=/etcd") - .WithEnvironment("ETCD_AUTO_COMPACTION_MODE", "revision") - .WithEnvironment("ETCD_AUTO_COMPACTION_RETENTION", "1000") - .WithEnvironment("ETCD_QUOTA_BACKEND_BYTES", "4294967296") - .WithEnvironment("ETCD_SNAPSHOT_COUNT", "50000") - .WithWaitStrategy(Wait.ForUnixContainer().UntilMessageIsLogged(".*ready to serve client requests.*")) - .Build(); - - var milvusContainer = new MilvusBuilder() - .WithImage("milvusdb/milvus:v2.3.10") - .WithNetwork(network) - .WithEtcdEndpoint("etcd:2379") - .DependsOn(etcdContainer) - .Build(); - - await milvusContainer.StartAsync(); - - try - { - - var client = new MilvusClient(milvusContainer.GetEndpoint()); - var version = await client.GetVersionAsync(); - - Assert.Equal("v2.3.10", version); - } - finally - { - await milvusContainer.StopAsync(); - } - } -} diff --git a/tests/Testcontainers.Milvus.Tests/Testcontainers.Milvus.Tests.csproj b/tests/Testcontainers.Milvus.Tests/Testcontainers.Milvus.Tests.csproj index 1ea90e495..dfb79e9e2 100644 --- a/tests/Testcontainers.Milvus.Tests/Testcontainers.Milvus.Tests.csproj +++ b/tests/Testcontainers.Milvus.Tests/Testcontainers.Milvus.Tests.csproj @@ -1,10 +1,8 @@ - + - net8.0 + net8.0 false false - enable - enable @@ -17,4 +15,4 @@ - + \ No newline at end of file diff --git a/tests/Testcontainers.Milvus.Tests/Usings.cs b/tests/Testcontainers.Milvus.Tests/Usings.cs new file mode 100644 index 000000000..4f8ec9c80 --- /dev/null +++ b/tests/Testcontainers.Milvus.Tests/Usings.cs @@ -0,0 +1,7 @@ +global using System.Threading.Tasks; +global using DotNet.Testcontainers.Builders; +global using DotNet.Testcontainers.Commons; +global using DotNet.Testcontainers.Networks; +global using JetBrains.Annotations; +global using Milvus.Client; +global using Xunit; \ No newline at end of file