From 85ab9b47b5ce3a910b2d4cff5b2b065aa4f3eb47 Mon Sep 17 00:00:00 2001 From: "Frank R. Haugen" Date: Thu, 25 Jan 2024 11:48:21 +0100 Subject: [PATCH 1/6] Initial create the module from template --- Testcontainers.sln | 7 ++ src/Testcontainers.Ollama/.editorconfig | 1 + .../Testcontainers.Ollama.csproj | 12 +++ .../Testcontainers.OllamaBuilder.cs | 86 +++++++++++++++++++ .../Testcontainers.OllamaConfiguration.cs | 63 ++++++++++++++ .../Testcontainers.OllamaContainer.cs | 16 ++++ src/Testcontainers.Ollama/Usings.cs | 10 +++ 7 files changed, 195 insertions(+) create mode 100644 src/Testcontainers.Ollama/.editorconfig create mode 100644 src/Testcontainers.Ollama/Testcontainers.Ollama.csproj create mode 100644 src/Testcontainers.Ollama/Testcontainers.OllamaBuilder.cs create mode 100644 src/Testcontainers.Ollama/Testcontainers.OllamaConfiguration.cs create mode 100644 src/Testcontainers.Ollama/Testcontainers.OllamaContainer.cs create mode 100644 src/Testcontainers.Ollama/Usings.cs diff --git a/Testcontainers.sln b/Testcontainers.sln index 49143c3ac..ec12ca759 100644 --- a/Testcontainers.sln +++ b/Testcontainers.sln @@ -187,6 +187,8 @@ 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.Ollama", "src\Testcontainers.Ollama\Testcontainers.Ollama.csproj", "{FDC88529-64F5-4F0A-95BE-8FBF653201C6}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -544,6 +546,10 @@ 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 + {FDC88529-64F5-4F0A-95BE-8FBF653201C6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {FDC88529-64F5-4F0A-95BE-8FBF653201C6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {FDC88529-64F5-4F0A-95BE-8FBF653201C6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {FDC88529-64F5-4F0A-95BE-8FBF653201C6}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(NestedProjects) = preSolution {5365F780-0E6C-41F0-B1B9-7DC34368F80C} = {673F23AE-7694-4BB9-ABD4-136D6C13634E} @@ -633,5 +639,6 @@ 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} + {FDC88529-64F5-4F0A-95BE-8FBF653201C6} = {673F23AE-7694-4BB9-ABD4-136D6C13634E} EndGlobalSection EndGlobal diff --git a/src/Testcontainers.Ollama/.editorconfig b/src/Testcontainers.Ollama/.editorconfig new file mode 100644 index 000000000..6f066619d --- /dev/null +++ b/src/Testcontainers.Ollama/.editorconfig @@ -0,0 +1 @@ +root = true \ No newline at end of file diff --git a/src/Testcontainers.Ollama/Testcontainers.Ollama.csproj b/src/Testcontainers.Ollama/Testcontainers.Ollama.csproj new file mode 100644 index 000000000..7048179d1 --- /dev/null +++ b/src/Testcontainers.Ollama/Testcontainers.Ollama.csproj @@ -0,0 +1,12 @@ + + + netstandard2.0;netstandard2.1 + latest + + + + + + + + \ No newline at end of file diff --git a/src/Testcontainers.Ollama/Testcontainers.OllamaBuilder.cs b/src/Testcontainers.Ollama/Testcontainers.OllamaBuilder.cs new file mode 100644 index 000000000..027f73b5d --- /dev/null +++ b/src/Testcontainers.Ollama/Testcontainers.OllamaBuilder.cs @@ -0,0 +1,86 @@ +namespace Testcontainers.Ollama; + +/// +[PublicAPI] +public sealed class Testcontainers.OllamaBuilder : ContainerBuilder +{ + /// + /// Initializes a new instance of the class. + /// + public Testcontainers.OllamaBuilder() + : this(new Testcontainers.OllamaConfiguration()) + { + // 1) To change the ContainerBuilder default configuration override the DockerResourceConfiguration property and the "Testcontainers.OllamaBuilder Init()" method. + // Append the module configuration to base.Init() e.g. base.Init().WithImage("alpine:3.17") to set the modules' default image. + + // 2) To customize the ContainerBuilder validation override the "void Validate()" method. + // Use Testcontainers' Guard.Argument(TType, string) or your own guard implementation to validate the module configuration. + + // 3) Add custom builder methods to extend the ContainerBuilder capabilities such as "Testcontainers.OllamaBuilder WithTestcontainers.OllamaConfig(object)". + // Merge the current module configuration with a new instance of the immutable Testcontainers.OllamaConfiguration type to update the module configuration. + + // DockerResourceConfiguration = Init().DockerResourceConfiguration; + } + + /// + /// Initializes a new instance of the class. + /// + /// The Docker resource configuration. + private Testcontainers.OllamaBuilder(Testcontainers.OllamaConfiguration resourceConfiguration) + : base(resourceConfiguration) + { + // DockerResourceConfiguration = resourceConfiguration; + } + + // /// + // protected override Testcontainers.OllamaConfiguration DockerResourceConfiguration { get; } + + // /// + // /// Sets the Testcontainers.Ollama config. + // /// + // /// The Testcontainers.Ollama config. + // /// A configured instance of . + // public Testcontainers.OllamaBuilder WithTestcontainers.OllamaConfig(object config) + // { + // // Extends the ContainerBuilder capabilities and holds a custom configuration in Testcontainers.OllamaConfiguration. + // // In case of a module requires other properties to represent itself, extend ContainerConfiguration. + // return Merge(DockerResourceConfiguration, new Testcontainers.OllamaConfiguration(config: config)); + // } + + /// + public override Testcontainers.OllamaContainer Build() + { + Validate(); + return new Testcontainers.OllamaContainer(DockerResourceConfiguration, TestcontainersSettings.Logger); + } + + // /// + // protected override Testcontainers.OllamaBuilder Init() + // { + // return base.Init(); + // } + + // /// + // protected override void Validate() + // { + // base.Validate(); + // } + + /// + protected override Testcontainers.OllamaBuilder Clone(IResourceConfiguration resourceConfiguration) + { + return Merge(DockerResourceConfiguration, new Testcontainers.OllamaConfiguration(resourceConfiguration)); + } + + /// + protected override Testcontainers.OllamaBuilder Clone(IContainerConfiguration resourceConfiguration) + { + return Merge(DockerResourceConfiguration, new Testcontainers.OllamaConfiguration(resourceConfiguration)); + } + + /// + protected override Testcontainers.OllamaBuilder Merge(Testcontainers.OllamaConfiguration oldValue, Testcontainers.OllamaConfiguration newValue) + { + return new Testcontainers.OllamaBuilder(new Testcontainers.OllamaConfiguration(oldValue, newValue)); + } +} \ No newline at end of file diff --git a/src/Testcontainers.Ollama/Testcontainers.OllamaConfiguration.cs b/src/Testcontainers.Ollama/Testcontainers.OllamaConfiguration.cs new file mode 100644 index 000000000..7d3ead5bc --- /dev/null +++ b/src/Testcontainers.Ollama/Testcontainers.OllamaConfiguration.cs @@ -0,0 +1,63 @@ +namespace Testcontainers.Ollama; + +/// +[PublicAPI] +public sealed class Testcontainers.OllamaConfiguration : ContainerConfiguration +{ + /// + /// Initializes a new instance of the class. + /// + /// The Testcontainers.Ollama config. + public Testcontainers.OllamaConfiguration(object config = null) + { + // // Sets the custom builder methods property values. + // Config = config; + } + + /// + /// Initializes a new instance of the class. + /// + /// The Docker resource configuration. + public Testcontainers.OllamaConfiguration(IResourceConfiguration 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 Testcontainers.OllamaConfiguration(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 Testcontainers.OllamaConfiguration(Testcontainers.OllamaConfiguration resourceConfiguration) + : this(new Testcontainers.OllamaConfiguration(), 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 Testcontainers.OllamaConfiguration(Testcontainers.OllamaConfiguration oldValue, Testcontainers.OllamaConfiguration newValue) + : base(oldValue, newValue) + { + // // Create an updated immutable copy of the module configuration. + // Config = BuildConfiguration.Combine(oldValue.Config, newValue.Config); + } + + // /// + // /// Gets the Testcontainers.Ollama config. + // /// + // public object Config { get; } +} \ No newline at end of file diff --git a/src/Testcontainers.Ollama/Testcontainers.OllamaContainer.cs b/src/Testcontainers.Ollama/Testcontainers.OllamaContainer.cs new file mode 100644 index 000000000..e48d1c6ae --- /dev/null +++ b/src/Testcontainers.Ollama/Testcontainers.OllamaContainer.cs @@ -0,0 +1,16 @@ +namespace Testcontainers.Ollama; + +/// +[PublicAPI] +public sealed class Testcontainers.OllamaContainer : DockerContainer +{ + /// + /// Initializes a new instance of the class. + /// + /// The container configuration. + /// The logger. + public Testcontainers.OllamaContainer(Testcontainers.OllamaConfiguration configuration, ILogger logger) + : base(configuration, logger) + { + } +} \ No newline at end of file diff --git a/src/Testcontainers.Ollama/Usings.cs b/src/Testcontainers.Ollama/Usings.cs new file mode 100644 index 000000000..f889bad0a --- /dev/null +++ b/src/Testcontainers.Ollama/Usings.cs @@ -0,0 +1,10 @@ +global using System; +global using System.Collections.Generic; +global using System.Linq; +global using Docker.DotNet.Models; +global using DotNet.Testcontainers; +global using DotNet.Testcontainers.Builders; +global using DotNet.Testcontainers.Configurations; +global using DotNet.Testcontainers.Containers; +global using JetBrains.Annotations; +global using Microsoft.Extensions.Logging; \ No newline at end of file From 8f548e43ef45c3d4055a88d542db445c036505f9 Mon Sep 17 00:00:00 2001 From: "Frank R. Haugen" Date: Thu, 25 Jan 2024 11:56:50 +0100 Subject: [PATCH 2/6] Added test project for Ollama module --- Testcontainers.sln | 7 +++++ .../Testcontainers.Ollama.csproj | 28 +++++++++++++++++++ tests/Testcontainers.Ollama/UnitTest1.cs | 19 +++++++++++++ tests/Testcontainers.Ollama/Usings.cs | 4 +++ 4 files changed, 58 insertions(+) create mode 100644 tests/Testcontainers.Ollama/Testcontainers.Ollama.csproj create mode 100644 tests/Testcontainers.Ollama/UnitTest1.cs create mode 100644 tests/Testcontainers.Ollama/Usings.cs diff --git a/Testcontainers.sln b/Testcontainers.sln index ec12ca759..52ffa3b1c 100644 --- a/Testcontainers.sln +++ b/Testcontainers.sln @@ -189,6 +189,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.WebDriver.Te EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.Ollama", "src\Testcontainers.Ollama\Testcontainers.Ollama.csproj", "{FDC88529-64F5-4F0A-95BE-8FBF653201C6}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.Ollama", "tests\Testcontainers.Ollama\Testcontainers.Ollama.csproj", "{0997BFAD-919D-482F-83E6-5DF9C4A1D313}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -550,6 +552,10 @@ Global {FDC88529-64F5-4F0A-95BE-8FBF653201C6}.Debug|Any CPU.Build.0 = Debug|Any CPU {FDC88529-64F5-4F0A-95BE-8FBF653201C6}.Release|Any CPU.ActiveCfg = Release|Any CPU {FDC88529-64F5-4F0A-95BE-8FBF653201C6}.Release|Any CPU.Build.0 = Release|Any CPU + {0997BFAD-919D-482F-83E6-5DF9C4A1D313}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {0997BFAD-919D-482F-83E6-5DF9C4A1D313}.Debug|Any CPU.Build.0 = Debug|Any CPU + {0997BFAD-919D-482F-83E6-5DF9C4A1D313}.Release|Any CPU.ActiveCfg = Release|Any CPU + {0997BFAD-919D-482F-83E6-5DF9C4A1D313}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(NestedProjects) = preSolution {5365F780-0E6C-41F0-B1B9-7DC34368F80C} = {673F23AE-7694-4BB9-ABD4-136D6C13634E} @@ -640,5 +646,6 @@ Global {27CDB869-A150-4593-958F-6F26E5391E7C} = {7164F1FB-7F24-444A-ACD2-2C329C2B3CCF} {EBA72C3B-57D5-43FF-A5B4-3D55B3B6D4C2} = {7164F1FB-7F24-444A-ACD2-2C329C2B3CCF} {FDC88529-64F5-4F0A-95BE-8FBF653201C6} = {673F23AE-7694-4BB9-ABD4-136D6C13634E} + {0997BFAD-919D-482F-83E6-5DF9C4A1D313} = {7164F1FB-7F24-444A-ACD2-2C329C2B3CCF} EndGlobalSection EndGlobal diff --git a/tests/Testcontainers.Ollama/Testcontainers.Ollama.csproj b/tests/Testcontainers.Ollama/Testcontainers.Ollama.csproj new file mode 100644 index 000000000..a43dca8fd --- /dev/null +++ b/tests/Testcontainers.Ollama/Testcontainers.Ollama.csproj @@ -0,0 +1,28 @@ + + + + net8.0 + false + false + + + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + + + + + + diff --git a/tests/Testcontainers.Ollama/UnitTest1.cs b/tests/Testcontainers.Ollama/UnitTest1.cs new file mode 100644 index 000000000..80489160c --- /dev/null +++ b/tests/Testcontainers.Ollama/UnitTest1.cs @@ -0,0 +1,19 @@ +namespace Testcontainers.Ollama; + +public class OllamaContainerTests : IAsyncLifetime +{ + [Fact] + public void Test1() + { + } + + /// + public async Task InitializeAsync() + { + } + + /// + public async Task DisposeAsync() + { + } +} diff --git a/tests/Testcontainers.Ollama/Usings.cs b/tests/Testcontainers.Ollama/Usings.cs new file mode 100644 index 000000000..38536e809 --- /dev/null +++ b/tests/Testcontainers.Ollama/Usings.cs @@ -0,0 +1,4 @@ +global using System.Threading.Tasks; +global using DotNet.Testcontainers.Commons; +global using Xunit; +global using Xunit.Abstractions; From fa48ecb599a80cd54b705bef3cfa5f6fe1883294 Mon Sep 17 00:00:00 2001 From: "Frank R. Haugen" Date: Thu, 25 Jan 2024 12:04:50 +0100 Subject: [PATCH 3/6] Correct any "wrongness" for setting up project and test --- Testcontainers.sln | 2 +- ...ners.OllamaBuilder.cs => OllamaBuilder.cs} | 27 ++++++++++--------- ...onfiguration.cs => OllamaConfiguration.cs} | 14 +++++----- ....OllamaContainer.cs => OllamaContainer.cs} | 4 +-- .../Testcontainers.Ollama.Tests.csproj} | 0 .../UnitTest1.cs | 2 +- .../Usings.cs | 0 7 files changed, 26 insertions(+), 23 deletions(-) rename src/Testcontainers.Ollama/{Testcontainers.OllamaBuilder.cs => OllamaBuilder.cs} (69%) rename src/Testcontainers.Ollama/{Testcontainers.OllamaConfiguration.cs => OllamaConfiguration.cs} (75%) rename src/Testcontainers.Ollama/{Testcontainers.OllamaContainer.cs => OllamaContainer.cs} (68%) rename tests/{Testcontainers.Ollama/Testcontainers.Ollama.csproj => Testcontainers.Ollama.Tests/Testcontainers.Ollama.Tests.csproj} (100%) rename tests/{Testcontainers.Ollama => Testcontainers.Ollama.Tests}/UnitTest1.cs (85%) rename tests/{Testcontainers.Ollama => Testcontainers.Ollama.Tests}/Usings.cs (100%) diff --git a/Testcontainers.sln b/Testcontainers.sln index 52ffa3b1c..228b264d2 100644 --- a/Testcontainers.sln +++ b/Testcontainers.sln @@ -189,7 +189,7 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.WebDriver.Te EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.Ollama", "src\Testcontainers.Ollama\Testcontainers.Ollama.csproj", "{FDC88529-64F5-4F0A-95BE-8FBF653201C6}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.Ollama", "tests\Testcontainers.Ollama\Testcontainers.Ollama.csproj", "{0997BFAD-919D-482F-83E6-5DF9C4A1D313}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Testcontainers.Ollama.Tests", "tests\Testcontainers.Ollama.Tests\Testcontainers.Ollama.Tests.csproj", "{0997BFAD-919D-482F-83E6-5DF9C4A1D313}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/src/Testcontainers.Ollama/Testcontainers.OllamaBuilder.cs b/src/Testcontainers.Ollama/OllamaBuilder.cs similarity index 69% rename from src/Testcontainers.Ollama/Testcontainers.OllamaBuilder.cs rename to src/Testcontainers.Ollama/OllamaBuilder.cs index 027f73b5d..7822b0c81 100644 --- a/src/Testcontainers.Ollama/Testcontainers.OllamaBuilder.cs +++ b/src/Testcontainers.Ollama/OllamaBuilder.cs @@ -2,13 +2,13 @@ namespace Testcontainers.Ollama; /// [PublicAPI] -public sealed class Testcontainers.OllamaBuilder : ContainerBuilder +public sealed class OllamaBuilder : ContainerBuilder { /// /// Initializes a new instance of the class. /// - public Testcontainers.OllamaBuilder() - : this(new Testcontainers.OllamaConfiguration()) + public OllamaBuilder() + : this(new OllamaConfiguration()) { // 1) To change the ContainerBuilder default configuration override the DockerResourceConfiguration property and the "Testcontainers.OllamaBuilder Init()" method. // Append the module configuration to base.Init() e.g. base.Init().WithImage("alpine:3.17") to set the modules' default image. @@ -26,7 +26,7 @@ public Testcontainers.OllamaBuilder() /// Initializes a new instance of the class. /// /// The Docker resource configuration. - private Testcontainers.OllamaBuilder(Testcontainers.OllamaConfiguration resourceConfiguration) + private OllamaBuilder(OllamaConfiguration resourceConfiguration) : base(resourceConfiguration) { // DockerResourceConfiguration = resourceConfiguration; @@ -48,10 +48,13 @@ private Testcontainers.OllamaBuilder(Testcontainers.OllamaConfiguration resource // } /// - public override Testcontainers.OllamaContainer Build() + protected override OllamaConfiguration DockerResourceConfiguration { get; } + + /// + public override OllamaContainer Build() { Validate(); - return new Testcontainers.OllamaContainer(DockerResourceConfiguration, TestcontainersSettings.Logger); + return new OllamaContainer(DockerResourceConfiguration, TestcontainersSettings.Logger); } // /// @@ -67,20 +70,20 @@ public override Testcontainers.OllamaContainer Build() // } /// - protected override Testcontainers.OllamaBuilder Clone(IResourceConfiguration resourceConfiguration) + protected override OllamaBuilder Clone(IResourceConfiguration resourceConfiguration) { - return Merge(DockerResourceConfiguration, new Testcontainers.OllamaConfiguration(resourceConfiguration)); + return Merge(DockerResourceConfiguration, new OllamaConfiguration(resourceConfiguration)); } /// - protected override Testcontainers.OllamaBuilder Clone(IContainerConfiguration resourceConfiguration) + protected override OllamaBuilder Clone(IContainerConfiguration resourceConfiguration) { - return Merge(DockerResourceConfiguration, new Testcontainers.OllamaConfiguration(resourceConfiguration)); + return Merge(DockerResourceConfiguration, new OllamaConfiguration(resourceConfiguration)); } /// - protected override Testcontainers.OllamaBuilder Merge(Testcontainers.OllamaConfiguration oldValue, Testcontainers.OllamaConfiguration newValue) + protected override OllamaBuilder Merge(OllamaConfiguration oldValue, OllamaConfiguration newValue) { - return new Testcontainers.OllamaBuilder(new Testcontainers.OllamaConfiguration(oldValue, newValue)); + return new OllamaBuilder(new OllamaConfiguration(oldValue, newValue)); } } \ No newline at end of file diff --git a/src/Testcontainers.Ollama/Testcontainers.OllamaConfiguration.cs b/src/Testcontainers.Ollama/OllamaConfiguration.cs similarity index 75% rename from src/Testcontainers.Ollama/Testcontainers.OllamaConfiguration.cs rename to src/Testcontainers.Ollama/OllamaConfiguration.cs index 7d3ead5bc..26aeb7b9d 100644 --- a/src/Testcontainers.Ollama/Testcontainers.OllamaConfiguration.cs +++ b/src/Testcontainers.Ollama/OllamaConfiguration.cs @@ -2,13 +2,13 @@ namespace Testcontainers.Ollama; /// [PublicAPI] -public sealed class Testcontainers.OllamaConfiguration : ContainerConfiguration +public sealed class OllamaConfiguration : ContainerConfiguration { /// /// Initializes a new instance of the class. /// /// The Testcontainers.Ollama config. - public Testcontainers.OllamaConfiguration(object config = null) + public OllamaConfiguration(object config = null) { // // Sets the custom builder methods property values. // Config = config; @@ -18,7 +18,7 @@ public Testcontainers.OllamaConfiguration(object config = null) /// Initializes a new instance of the class. /// /// The Docker resource configuration. - public Testcontainers.OllamaConfiguration(IResourceConfiguration resourceConfiguration) + public OllamaConfiguration(IResourceConfiguration resourceConfiguration) : base(resourceConfiguration) { // Passes the configuration upwards to the base implementations to create an updated immutable copy. @@ -28,7 +28,7 @@ public Testcontainers.OllamaConfiguration(IResourceConfiguration class. /// /// The Docker resource configuration. - public Testcontainers.OllamaConfiguration(IContainerConfiguration resourceConfiguration) + public OllamaConfiguration(IContainerConfiguration resourceConfiguration) : base(resourceConfiguration) { // Passes the configuration upwards to the base implementations to create an updated immutable copy. @@ -38,8 +38,8 @@ public Testcontainers.OllamaConfiguration(IContainerConfiguration resourceConfig /// Initializes a new instance of the class. /// /// The Docker resource configuration. - public Testcontainers.OllamaConfiguration(Testcontainers.OllamaConfiguration resourceConfiguration) - : this(new Testcontainers.OllamaConfiguration(), resourceConfiguration) + public OllamaConfiguration(OllamaConfiguration resourceConfiguration) + : this(new OllamaConfiguration(), resourceConfiguration) { // Passes the configuration upwards to the base implementations to create an updated immutable copy. } @@ -49,7 +49,7 @@ public Testcontainers.OllamaConfiguration(Testcontainers.OllamaConfiguration res /// /// The old Docker resource configuration. /// The new Docker resource configuration. - public Testcontainers.OllamaConfiguration(Testcontainers.OllamaConfiguration oldValue, Testcontainers.OllamaConfiguration newValue) + public OllamaConfiguration(OllamaConfiguration oldValue, OllamaConfiguration newValue) : base(oldValue, newValue) { // // Create an updated immutable copy of the module configuration. diff --git a/src/Testcontainers.Ollama/Testcontainers.OllamaContainer.cs b/src/Testcontainers.Ollama/OllamaContainer.cs similarity index 68% rename from src/Testcontainers.Ollama/Testcontainers.OllamaContainer.cs rename to src/Testcontainers.Ollama/OllamaContainer.cs index e48d1c6ae..4d41449c5 100644 --- a/src/Testcontainers.Ollama/Testcontainers.OllamaContainer.cs +++ b/src/Testcontainers.Ollama/OllamaContainer.cs @@ -2,14 +2,14 @@ namespace Testcontainers.Ollama; /// [PublicAPI] -public sealed class Testcontainers.OllamaContainer : DockerContainer +public sealed class OllamaContainer : DockerContainer { /// /// Initializes a new instance of the class. /// /// The container configuration. /// The logger. - public Testcontainers.OllamaContainer(Testcontainers.OllamaConfiguration configuration, ILogger logger) + public OllamaContainer(OllamaConfiguration configuration, ILogger logger) : base(configuration, logger) { } diff --git a/tests/Testcontainers.Ollama/Testcontainers.Ollama.csproj b/tests/Testcontainers.Ollama.Tests/Testcontainers.Ollama.Tests.csproj similarity index 100% rename from tests/Testcontainers.Ollama/Testcontainers.Ollama.csproj rename to tests/Testcontainers.Ollama.Tests/Testcontainers.Ollama.Tests.csproj diff --git a/tests/Testcontainers.Ollama/UnitTest1.cs b/tests/Testcontainers.Ollama.Tests/UnitTest1.cs similarity index 85% rename from tests/Testcontainers.Ollama/UnitTest1.cs rename to tests/Testcontainers.Ollama.Tests/UnitTest1.cs index 80489160c..0afc30313 100644 --- a/tests/Testcontainers.Ollama/UnitTest1.cs +++ b/tests/Testcontainers.Ollama.Tests/UnitTest1.cs @@ -1,4 +1,4 @@ -namespace Testcontainers.Ollama; +namespace Testcontainers.Ollama.Tests; public class OllamaContainerTests : IAsyncLifetime { diff --git a/tests/Testcontainers.Ollama/Usings.cs b/tests/Testcontainers.Ollama.Tests/Usings.cs similarity index 100% rename from tests/Testcontainers.Ollama/Usings.cs rename to tests/Testcontainers.Ollama.Tests/Usings.cs From 49fa3a90fb17b2b4d382f46a4afc73027365bc32 Mon Sep 17 00:00:00 2001 From: "Frank R. Haugen" Date: Thu, 25 Jan 2024 19:57:20 +0100 Subject: [PATCH 4/6] Added the nitty-gritty of the module --- docs/modules/index.md | 1 + src/Testcontainers.Ollama/OllamaBuilder.cs | 75 +++++++++--------- .../OllamaConfiguration.cs | 44 +++++++---- src/Testcontainers.Ollama/OllamaContainer.cs | 23 +++++- src/Testcontainers.Ollama/OllamaModels.cs | 76 +++++++++++++++++++ src/Testcontainers.Ollama/Usings.cs | 11 +-- .../TestOutputHelperExtensions.cs | 22 ++++++ .../TestOutputLogger.cs | 49 ++++++++++++ .../Testcontainers.Commons.csproj | 1 + .../OllamaContainerTests.cs | 47 ++++++++++++ .../Testcontainers.Ollama.Tests.csproj | 1 + .../Testcontainers.Ollama.Tests/UnitTest1.cs | 19 ----- tests/Testcontainers.Ollama.Tests/Usings.cs | 5 ++ 13 files changed, 295 insertions(+), 79 deletions(-) create mode 100644 src/Testcontainers.Ollama/OllamaModels.cs create mode 100644 tests/Testcontainers.Commons/TestOutputHelperExtensions.cs create mode 100644 tests/Testcontainers.Commons/TestOutputLogger.cs create mode 100644 tests/Testcontainers.Ollama.Tests/OllamaContainerTests.cs delete mode 100644 tests/Testcontainers.Ollama.Tests/UnitTest1.cs diff --git a/docs/modules/index.md b/docs/modules/index.md index c85f7fabc..40b24a835 100644 --- a/docs/modules/index.md +++ b/docs/modules/index.md @@ -51,6 +51,7 @@ await moduleNameContainer.StartAsync(); | MySQL | `mysql:8.0` | [NuGet](https://www.nuget.org/packages/Testcontainers.MySql) | [Source](https://github.com/testcontainers/testcontainers-dotnet/tree/develop/src/Testcontainers.MySql) | | NATS | `nats:2.9` | [NuGet](https://www.nuget.org/packages/Testcontainers.Nats) | [Source](https://github.com/testcontainers/testcontainers-dotnet/tree/develop/src/Testcontainers.Nats) | | Neo4j | `neo4j:5.4` | [NuGet](https://www.nuget.org/packages/Testcontainers.Neo4j) | [Source](https://github.com/testcontainers/testcontainers-dotnet/tree/develop/src/Testcontainers.Neo4j) | +| Ollama | `ollama/ollama:latest` | [NuGet](https://www.nuget.org/packages/Testcontainers.Ollama) | [Source](https://github.com/testcontainers/testcontainers-dotnet/tree/develop/src/Testcontainers.Ollama) | | Oracle | `gvenzl/oracle-xe:21.3.0-slim-faststart` | [NuGet](https://www.nuget.org/packages/Testcontainers.Oracle) | [Source](https://github.com/testcontainers/testcontainers-dotnet/tree/develop/src/Testcontainers.Oracle) | | Papercut | `jijiechen/papercut:latest` | [NuGet](https://www.nuget.org/packages/Testcontainers.Papercut) | [Source](https://github.com/testcontainers/testcontainers-dotnet/tree/develop/src/Testcontainers.Papercut) | | PostgreSQL | `postgres:15.1` | [NuGet](https://www.nuget.org/packages/Testcontainers.PostgreSql) | [Source](https://github.com/testcontainers/testcontainers-dotnet/tree/develop/src/Testcontainers.PostgreSql) | diff --git a/src/Testcontainers.Ollama/OllamaBuilder.cs b/src/Testcontainers.Ollama/OllamaBuilder.cs index 7822b0c81..72013826c 100644 --- a/src/Testcontainers.Ollama/OllamaBuilder.cs +++ b/src/Testcontainers.Ollama/OllamaBuilder.cs @@ -5,51 +5,37 @@ namespace Testcontainers.Ollama; public sealed class OllamaBuilder : ContainerBuilder { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// public OllamaBuilder() : this(new OllamaConfiguration()) { - // 1) To change the ContainerBuilder default configuration override the DockerResourceConfiguration property and the "Testcontainers.OllamaBuilder Init()" method. - // Append the module configuration to base.Init() e.g. base.Init().WithImage("alpine:3.17") to set the modules' default image. - - // 2) To customize the ContainerBuilder validation override the "void Validate()" method. - // Use Testcontainers' Guard.Argument(TType, string) or your own guard implementation to validate the module configuration. - - // 3) Add custom builder methods to extend the ContainerBuilder capabilities such as "Testcontainers.OllamaBuilder WithTestcontainers.OllamaConfig(object)". - // Merge the current module configuration with a new instance of the immutable Testcontainers.OllamaConfiguration type to update the module configuration. - - // DockerResourceConfiguration = Init().DockerResourceConfiguration; + DockerResourceConfiguration = Init().DockerResourceConfiguration; } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The Docker resource configuration. private OllamaBuilder(OllamaConfiguration resourceConfiguration) : base(resourceConfiguration) { - // DockerResourceConfiguration = resourceConfiguration; + DockerResourceConfiguration = resourceConfiguration; } - // /// - // protected override Testcontainers.OllamaConfiguration DockerResourceConfiguration { get; } - - // /// - // /// Sets the Testcontainers.Ollama config. - // /// - // /// The Testcontainers.Ollama config. - // /// A configured instance of . - // public Testcontainers.OllamaBuilder WithTestcontainers.OllamaConfig(object config) - // { - // // Extends the ContainerBuilder capabilities and holds a custom configuration in Testcontainers.OllamaConfiguration. - // // In case of a module requires other properties to represent itself, extend ContainerConfiguration. - // return Merge(DockerResourceConfiguration, new Testcontainers.OllamaConfiguration(config: config)); - // } - /// protected override OllamaConfiguration DockerResourceConfiguration { get; } + /// + /// Sets the Testcontainers.Ollama config. + /// + /// The Testcontainers.Ollama config. + /// A configured instance of . + public OllamaBuilder OllamaConfig(OllamaConfiguration config) + { + return Merge(DockerResourceConfiguration, config); + } + /// public override OllamaContainer Build() { @@ -57,17 +43,30 @@ public override OllamaContainer Build() return new OllamaContainer(DockerResourceConfiguration, TestcontainersSettings.Logger); } - // /// - // protected override Testcontainers.OllamaBuilder Init() - // { - // return base.Init(); - // } + /// + protected override void Validate() + { + Guard.Argument(DockerResourceConfiguration.Port, nameof(DockerResourceConfiguration.Port)).ThrowIf(info => info.Value is < 1 or > 65535, info => new ArgumentOutOfRangeException(info.Name, info.Value, $"The port must be between 1 and 65535.")); + Guard.Argument(DockerResourceConfiguration.ModelName, nameof(DockerResourceConfiguration.ModelName)).NotNull().NotEmpty(); + Guard.Argument(DockerResourceConfiguration.ImageName, nameof(DockerResourceConfiguration.ImageName)).NotNull().NotEmpty(); + Guard.Argument(DockerResourceConfiguration.HostName, nameof(DockerResourceConfiguration.HostName)).NotNull().NotEmpty(); + Guard.Argument(DockerResourceConfiguration.Schema, nameof(DockerResourceConfiguration.Schema)).NotNull().NotEmpty(); + + base.Validate(); + } - // /// - // protected override void Validate() - // { - // base.Validate(); - // } + /// + protected override OllamaBuilder Init() + { + return base.Init() + .WithName("ollama-container") + .WithImage(new DockerImage(DockerResourceConfiguration.ImageName)) + .WithHostname(DockerResourceConfiguration.HostName) + .WithPortBinding(DockerResourceConfiguration.Port, DockerResourceConfiguration.Port) + .WithVolumeMount("ollama", "/root/.ollama") + .WithExposedPort(DockerResourceConfiguration.Port) + ; + } /// protected override OllamaBuilder Clone(IResourceConfiguration resourceConfiguration) diff --git a/src/Testcontainers.Ollama/OllamaConfiguration.cs b/src/Testcontainers.Ollama/OllamaConfiguration.cs index 26aeb7b9d..b3c3c866d 100644 --- a/src/Testcontainers.Ollama/OllamaConfiguration.cs +++ b/src/Testcontainers.Ollama/OllamaConfiguration.cs @@ -5,17 +5,22 @@ namespace Testcontainers.Ollama; public sealed class OllamaConfiguration : ContainerConfiguration { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// - /// The Testcontainers.Ollama config. - public OllamaConfiguration(object config = null) + /// + /// + /// + /// + public OllamaConfiguration(string modelName = null, string schema = null, string hostName = null, int? port = null) { - // // Sets the custom builder methods property values. - // Config = config; + ModelName = modelName; + Schema = schema; + HostName = hostName; + Port = port ?? Port; } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The Docker resource configuration. public OllamaConfiguration(IResourceConfiguration resourceConfiguration) @@ -25,7 +30,7 @@ public OllamaConfiguration(IResourceConfiguration res } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The Docker resource configuration. public OllamaConfiguration(IContainerConfiguration resourceConfiguration) @@ -35,7 +40,7 @@ public OllamaConfiguration(IContainerConfiguration resourceConfiguration) } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The Docker resource configuration. public OllamaConfiguration(OllamaConfiguration resourceConfiguration) @@ -45,19 +50,26 @@ public OllamaConfiguration(OllamaConfiguration resourceConfiguration) } /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The old Docker resource configuration. /// The new Docker resource configuration. public OllamaConfiguration(OllamaConfiguration oldValue, OllamaConfiguration newValue) : base(oldValue, newValue) { - // // Create an updated immutable copy of the module configuration. - // Config = BuildConfiguration.Combine(oldValue.Config, newValue.Config); + ModelName = BuildConfiguration.Combine(oldValue.ModelName, newValue.ModelName); + Schema = BuildConfiguration.Combine(oldValue.Schema, newValue.Schema); + HostName = BuildConfiguration.Combine(oldValue.HostName, newValue.HostName); + Port = BuildConfiguration.Combine(oldValue.Port, newValue.Port); } - - // /// - // /// Gets the Testcontainers.Ollama config. - // /// - // public object Config { get; } + + public string ModelName { get; set; } = OllamaModels.Llama2; + public string Schema { get; set; } = "http"; + public string HostName { get; set; } = "localhost"; + public int Port { get; set; } = 11434; + + /// + /// Gets the name of the Docker image to use. + /// + public string ImageName { get; } = "ollama/ollama:latest"; } \ No newline at end of file diff --git a/src/Testcontainers.Ollama/OllamaContainer.cs b/src/Testcontainers.Ollama/OllamaContainer.cs index 4d41449c5..6234cf574 100644 --- a/src/Testcontainers.Ollama/OllamaContainer.cs +++ b/src/Testcontainers.Ollama/OllamaContainer.cs @@ -5,12 +5,33 @@ namespace Testcontainers.Ollama; public sealed class OllamaContainer : DockerContainer { /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// /// The container configuration. /// The logger. public OllamaContainer(OllamaConfiguration configuration, ILogger logger) : base(configuration, logger) { + ModelName = configuration.ModelName; + Schema = configuration.Schema; + HostName = configuration.HostName; + Port = configuration.Port; + ImageName = configuration.ImageName; } + + public string GetBaseUrl() => $"{Schema}://{HostName}:{Port}/api"; + + public string Schema { get; } + public string HostName { get; } + public int Port { get; } + + /// + /// Gets the name of the Docker image to use. + /// + public string ImageName { get; } + + /// + /// Gets the name of the model to run. + /// + public string ModelName { get; } } \ No newline at end of file diff --git a/src/Testcontainers.Ollama/OllamaModels.cs b/src/Testcontainers.Ollama/OllamaModels.cs new file mode 100644 index 000000000..315696f1e --- /dev/null +++ b/src/Testcontainers.Ollama/OllamaModels.cs @@ -0,0 +1,76 @@ +namespace Testcontainers.Ollama +{ + /// + /// A selection of OLLAMA models from the readme. + /// + /// + /// See: https://github.com/ollama/ollama?tab=readme-ov-file#model-library + /// + public static class OllamaModels + { + /// + /// Llama 2: 7B parameters, Size: 3.8GB, Command: ollama run llama2 + /// + public const string Llama2 = "llama2"; + + /// + /// Mistral: 7B parameters, Size: 4.1GB, Command: ollama run mistral + /// + public const string Mistral = "mistral"; + + /// + /// Dolphin Phi: 2.7B parameters, Size: 1.6GB, Command: ollama run dolphin-phi + /// + public const string DolphinPhi = "dolphin-phi"; + + /// + /// Phi-2: 2.7B parameters, Size: 1.7GB, Command: ollama run phi + /// + public const string Phi2 = "phi"; + + /// + /// Neural Chat: 7B parameters, Size: 4.1GB, Command: ollama run neural-chat + /// + public const string NeuralChat = "neural-chat"; + + /// + /// Starling: 7B parameters, Size: 4.1GB, Command: ollama run starling-lm + /// + public const string Starling = "starling-lm"; + + /// + /// Code Llama: 7B parameters, Size: 3.8GB, Command: ollama run codellama + /// + public const string CodeLlama = "codellama"; + + /// + /// Llama 2 Uncensored: 7B parameters, Size: 3.8GB, Command: ollama run llama2-uncensored + /// + public const string Llama2Uncensored = "llama2-uncensored"; + + /// + /// Llama 2 13B: 13B parameters, Size: 7.3GB, Command: ollama run llama2:13b + /// + public const string Llama213B = "llama2:13b"; + + /// + /// Llama 2 70B: 70B parameters, Size: 39GB, Command: ollama run llama2:70b + /// + public const string Llama270B = "llama2:70b"; + + /// + /// Orca Mini: 3B parameters, Size: 1.9GB, Command: ollama run orca-mini + /// + public const string OrcaMini = "orca-mini"; + + /// + /// Vicuna: 7B parameters, Size: 3.8GB, Command: ollama run vicuna + /// + public const string Vicuna = "vicuna"; + + /// + /// LLaVA: 7B parameters, Size: 4.5GB, Command: ollama run llava + /// + public const string LLaVA = "llava"; + } +} \ No newline at end of file diff --git a/src/Testcontainers.Ollama/Usings.cs b/src/Testcontainers.Ollama/Usings.cs index f889bad0a..a0845cb29 100644 --- a/src/Testcontainers.Ollama/Usings.cs +++ b/src/Testcontainers.Ollama/Usings.cs @@ -1,10 +1,11 @@ -global using System; -global using System.Collections.Generic; -global using System.Linq; global using Docker.DotNet.Models; -global using DotNet.Testcontainers; global using DotNet.Testcontainers.Builders; global using DotNet.Testcontainers.Configurations; global using DotNet.Testcontainers.Containers; +global using DotNet.Testcontainers; global using JetBrains.Annotations; -global using Microsoft.Extensions.Logging; \ No newline at end of file +global using Microsoft.Extensions.Logging; +global using DotNet.Testcontainers.Images; +global using System.Linq; +global using System.Threading.Tasks; +global using System; \ No newline at end of file diff --git a/tests/Testcontainers.Commons/TestOutputHelperExtensions.cs b/tests/Testcontainers.Commons/TestOutputHelperExtensions.cs new file mode 100644 index 000000000..4dbb8f490 --- /dev/null +++ b/tests/Testcontainers.Commons/TestOutputHelperExtensions.cs @@ -0,0 +1,22 @@ +#nullable enable +using System.Text.Json; +using System.Text.Json.Serialization; +using Xunit.Abstractions; + +namespace DotNet.Testcontainers.Commons +{ + public static class TestOutputHelperExtensions + { + public static void WriteJson(this ITestOutputHelper testOutputHelper, T source, JsonSerializerOptions? jsonSerializerOptions = null) + { + jsonSerializerOptions ??= new JsonSerializerOptions + { + WriteIndented = true, + Converters = { new JsonStringEnumConverter()}, + MaxDepth = 64, + }; + var json = JsonSerializer.Serialize(source, jsonSerializerOptions); + testOutputHelper.WriteLine(json); + } + } +} \ No newline at end of file diff --git a/tests/Testcontainers.Commons/TestOutputLogger.cs b/tests/Testcontainers.Commons/TestOutputLogger.cs new file mode 100644 index 000000000..7796c31a2 --- /dev/null +++ b/tests/Testcontainers.Commons/TestOutputLogger.cs @@ -0,0 +1,49 @@ +using Microsoft.Extensions.Logging; +using Xunit.Abstractions; + +namespace DotNet.Testcontainers.Commons; + +public class TestOutputLogger : ILogger +{ + private readonly string _categoryName; + private readonly LogLevel _logLevel; + private readonly ITestOutputHelper _testOutputHelper; + + public TestOutputLogger(string categoryName, ITestOutputHelper testOutputHelper, LogLevel logLevel = LogLevel.Information) + { + _categoryName = categoryName; + _testOutputHelper = testOutputHelper; + _logLevel = logLevel; + } + + /// + public void Log(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func formatter) + { + if (!IsEnabled(logLevel)) + return; + + if (formatter == null) + throw new ArgumentNullException(nameof(formatter)); + + var message = formatter(state, exception); + if (string.IsNullOrEmpty(message)) + { + return; + } + + _testOutputHelper.WriteLine($"{logLevel}: {_categoryName}: {message}"); + } + + /// + public bool IsEnabled(LogLevel logLevel) + { + return logLevel >= _logLevel; + } + + /// + public IDisposable BeginScope(TState state) + { + return null!; + } + +} \ No newline at end of file diff --git a/tests/Testcontainers.Commons/Testcontainers.Commons.csproj b/tests/Testcontainers.Commons/Testcontainers.Commons.csproj index 0fce12a00..4810e26a0 100644 --- a/tests/Testcontainers.Commons/Testcontainers.Commons.csproj +++ b/tests/Testcontainers.Commons/Testcontainers.Commons.csproj @@ -8,6 +8,7 @@ + diff --git a/tests/Testcontainers.Ollama.Tests/OllamaContainerTests.cs b/tests/Testcontainers.Ollama.Tests/OllamaContainerTests.cs new file mode 100644 index 000000000..c0c602310 --- /dev/null +++ b/tests/Testcontainers.Ollama.Tests/OllamaContainerTests.cs @@ -0,0 +1,47 @@ +namespace Testcontainers.Ollama.Tests; + +public class OllamaContainerTests : IAsyncLifetime +{ + private readonly ITestOutputHelper _testOutputHelper; + private OllamaContainer _ollamaContainer; + + public OllamaContainerTests(ITestOutputHelper testOutputHelper) + { + _testOutputHelper = testOutputHelper; + } + + public async Task InitializeAsync() + { + TestcontainersSettings.Logger = new TestOutputLogger(nameof(OllamaContainerTests), _testOutputHelper); + _ollamaContainer = new OllamaBuilder().Build(); + await _ollamaContainer.StartAsync(); + } + + public async Task DisposeAsync() + { + await _ollamaContainer.DisposeAsync().AsTask(); + } + + [Fact] + [Trait(nameof(DockerCli.DockerPlatform), nameof(DockerCli.DockerPlatform.Linux))] + public async Task OllamaContainerReturnsSuccessful() + { + var client = new OllamaApiClient(_ollamaContainer.GetBaseUrl(), _ollamaContainer.ModelName); + + var chatRequest = new ChatRequest() { + Model = _ollamaContainer.ModelName, + Stream = false, + Messages = new List() + { + new Message() { Content = "You are very helpful", Role = ChatRole.System }, + new Message() { Content = "Hello", Role = ChatRole.User }, + } + }; + + var response = await client.SendChat(chatRequest, stream => { }); + _testOutputHelper.WriteJson(response); + + Assert.True(response.Any()); + } + +} diff --git a/tests/Testcontainers.Ollama.Tests/Testcontainers.Ollama.Tests.csproj b/tests/Testcontainers.Ollama.Tests/Testcontainers.Ollama.Tests.csproj index a43dca8fd..3da16aee4 100644 --- a/tests/Testcontainers.Ollama.Tests/Testcontainers.Ollama.Tests.csproj +++ b/tests/Testcontainers.Ollama.Tests/Testcontainers.Ollama.Tests.csproj @@ -8,6 +8,7 @@ + runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/tests/Testcontainers.Ollama.Tests/UnitTest1.cs b/tests/Testcontainers.Ollama.Tests/UnitTest1.cs deleted file mode 100644 index 0afc30313..000000000 --- a/tests/Testcontainers.Ollama.Tests/UnitTest1.cs +++ /dev/null @@ -1,19 +0,0 @@ -namespace Testcontainers.Ollama.Tests; - -public class OllamaContainerTests : IAsyncLifetime -{ - [Fact] - public void Test1() - { - } - - /// - public async Task InitializeAsync() - { - } - - /// - public async Task DisposeAsync() - { - } -} diff --git a/tests/Testcontainers.Ollama.Tests/Usings.cs b/tests/Testcontainers.Ollama.Tests/Usings.cs index 38536e809..e8ee5c203 100644 --- a/tests/Testcontainers.Ollama.Tests/Usings.cs +++ b/tests/Testcontainers.Ollama.Tests/Usings.cs @@ -2,3 +2,8 @@ global using DotNet.Testcontainers.Commons; global using Xunit; global using Xunit.Abstractions; +global using System.Collections.Generic; +global using System.Linq; +global using DotNet.Testcontainers.Configurations; +global using OllamaSharp; +global using OllamaSharp.Models.Chat; From 952e5cf1bb0fed97717edcd26e22126dc8c24e5e Mon Sep 17 00:00:00 2001 From: "Frank R. Haugen" Date: Thu, 25 Jan 2024 21:15:20 +0100 Subject: [PATCH 5/6] Cleanup --- src/Testcontainers.Ollama/OllamaBuilder.cs | 158 +++++++++--------- .../OllamaConfiguration.cs | 142 ++++++++-------- src/Testcontainers.Ollama/OllamaContainer.cs | 77 +++++---- src/Testcontainers.Ollama/Usings.cs | 6 +- .../OllamaContainerTests.cs | 88 +++++----- 5 files changed, 253 insertions(+), 218 deletions(-) diff --git a/src/Testcontainers.Ollama/OllamaBuilder.cs b/src/Testcontainers.Ollama/OllamaBuilder.cs index 72013826c..18672fd19 100644 --- a/src/Testcontainers.Ollama/OllamaBuilder.cs +++ b/src/Testcontainers.Ollama/OllamaBuilder.cs @@ -1,88 +1,96 @@ -namespace Testcontainers.Ollama; - -/// -[PublicAPI] -public sealed class OllamaBuilder : ContainerBuilder +namespace Testcontainers.Ollama { - /// - /// Initializes a new instance of the class. - /// - public OllamaBuilder() - : this(new OllamaConfiguration()) + /// + [PublicAPI] + public sealed class OllamaBuilder : ContainerBuilder { - DockerResourceConfiguration = Init().DockerResourceConfiguration; - } + /// + /// Initializes a new instance of the class. + /// + public OllamaBuilder() + : this(new OllamaConfiguration()) + { + DockerResourceConfiguration = Init().DockerResourceConfiguration; + } - /// - /// Initializes a new instance of the class. - /// - /// The Docker resource configuration. - private OllamaBuilder(OllamaConfiguration resourceConfiguration) - : base(resourceConfiguration) - { - DockerResourceConfiguration = resourceConfiguration; - } + /// + /// Initializes a new instance of the class. + /// + /// The Docker resource configuration. + private OllamaBuilder(OllamaConfiguration resourceConfiguration) + : base(resourceConfiguration) + { + DockerResourceConfiguration = resourceConfiguration; + } - /// - protected override OllamaConfiguration DockerResourceConfiguration { get; } + /// + protected override OllamaConfiguration DockerResourceConfiguration { get; } - /// - /// Sets the Testcontainers.Ollama config. - /// - /// The Testcontainers.Ollama config. - /// A configured instance of . - public OllamaBuilder OllamaConfig(OllamaConfiguration config) - { - return Merge(DockerResourceConfiguration, config); - } + /// + /// Sets the Testcontainers.Ollama config. + /// + /// The Testcontainers.Ollama config. + /// A configured instance of . + public OllamaBuilder OllamaConfig(OllamaConfiguration config) + { + return Merge(DockerResourceConfiguration, config); + } - /// - public override OllamaContainer Build() - { - Validate(); - return new OllamaContainer(DockerResourceConfiguration, TestcontainersSettings.Logger); - } + /// + public override OllamaContainer Build() + { + Validate(); + return new OllamaContainer(DockerResourceConfiguration, TestcontainersSettings.Logger); + } - /// - protected override void Validate() - { - Guard.Argument(DockerResourceConfiguration.Port, nameof(DockerResourceConfiguration.Port)).ThrowIf(info => info.Value is < 1 or > 65535, info => new ArgumentOutOfRangeException(info.Name, info.Value, $"The port must be between 1 and 65535.")); - Guard.Argument(DockerResourceConfiguration.ModelName, nameof(DockerResourceConfiguration.ModelName)).NotNull().NotEmpty(); - Guard.Argument(DockerResourceConfiguration.ImageName, nameof(DockerResourceConfiguration.ImageName)).NotNull().NotEmpty(); - Guard.Argument(DockerResourceConfiguration.HostName, nameof(DockerResourceConfiguration.HostName)).NotNull().NotEmpty(); - Guard.Argument(DockerResourceConfiguration.Schema, nameof(DockerResourceConfiguration.Schema)).NotNull().NotEmpty(); - - base.Validate(); - } + /// + protected override void Validate() + { + Guard.Argument(DockerResourceConfiguration.ModelName, nameof(DockerResourceConfiguration.ModelName)).NotNull().NotEmpty(); + base.Validate(); + } - /// - protected override OllamaBuilder Init() - { - return base.Init() - .WithName("ollama-container") - .WithImage(new DockerImage(DockerResourceConfiguration.ImageName)) - .WithHostname(DockerResourceConfiguration.HostName) - .WithPortBinding(DockerResourceConfiguration.Port, DockerResourceConfiguration.Port) - .WithVolumeMount("ollama", "/root/.ollama") - .WithExposedPort(DockerResourceConfiguration.Port) - ; - } + /// + protected override OllamaBuilder Init() + { + return base.Init() + .WithImage(new DockerImage(OllamaConfiguration.ImageName)) + .WithPortBinding(OllamaConfiguration.DefaultPort, true) + .WithVolumeMount(OllamaConfiguration.DefaultVolumeName, OllamaConfiguration.DefaultVolumePath) + ; + } - /// - protected override OllamaBuilder Clone(IResourceConfiguration resourceConfiguration) - { - return Merge(DockerResourceConfiguration, new OllamaConfiguration(resourceConfiguration)); - } + /// + protected override OllamaBuilder Clone(IResourceConfiguration resourceConfiguration) + { + return Merge(DockerResourceConfiguration, new OllamaConfiguration(resourceConfiguration)); + } - /// - protected override OllamaBuilder Clone(IContainerConfiguration resourceConfiguration) - { - return Merge(DockerResourceConfiguration, new OllamaConfiguration(resourceConfiguration)); - } + /// + protected override OllamaBuilder Clone(IContainerConfiguration resourceConfiguration) + { + return Merge(DockerResourceConfiguration, new OllamaConfiguration(resourceConfiguration)); + } - /// - protected override OllamaBuilder Merge(OllamaConfiguration oldValue, OllamaConfiguration newValue) - { - return new OllamaBuilder(new OllamaConfiguration(oldValue, newValue)); + /// + protected override OllamaBuilder Merge(OllamaConfiguration oldValue, OllamaConfiguration newValue) + { + return new OllamaBuilder(new OllamaConfiguration(oldValue, newValue)); + } + + /// + /// Sets the name of the model to run. + /// + /// The name of the model to run. + /// A configured instance of . + /// The name of the model to run is . + /// The name of the model to run is empty. + /// + /// The name of the model to run is required. + /// + public OllamaBuilder WithModelName(string name) + { + return Merge(DockerResourceConfiguration, new OllamaConfiguration(DockerResourceConfiguration) {ModelName = name}); + } } } \ No newline at end of file diff --git a/src/Testcontainers.Ollama/OllamaConfiguration.cs b/src/Testcontainers.Ollama/OllamaConfiguration.cs index b3c3c866d..d3eb7e544 100644 --- a/src/Testcontainers.Ollama/OllamaConfiguration.cs +++ b/src/Testcontainers.Ollama/OllamaConfiguration.cs @@ -1,75 +1,85 @@ -namespace Testcontainers.Ollama; - -/// -[PublicAPI] -public sealed class OllamaConfiguration : ContainerConfiguration +namespace Testcontainers.Ollama { - /// - /// Initializes a new instance of the class. - /// - /// - /// - /// - /// - public OllamaConfiguration(string modelName = null, string schema = null, string hostName = null, int? port = null) + /// + [PublicAPI] + public sealed class OllamaConfiguration : ContainerConfiguration { - ModelName = modelName; - Schema = schema; - HostName = hostName; - Port = port ?? Port; - } + /// + /// Initializes a new instance of the class. + /// + /// + /// + /// + /// + public OllamaConfiguration(string modelName = null, string schema = null, int? port = null) + { + ModelName = modelName; + } - /// - /// Initializes a new instance of the class. - /// - /// The Docker resource configuration. - public OllamaConfiguration(IResourceConfiguration 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 OllamaConfiguration(IResourceConfiguration 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 OllamaConfiguration(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 OllamaConfiguration(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 OllamaConfiguration(OllamaConfiguration resourceConfiguration) - : this(new OllamaConfiguration(), 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 OllamaConfiguration(OllamaConfiguration resourceConfiguration) + : this(new OllamaConfiguration(), 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 OllamaConfiguration(OllamaConfiguration oldValue, OllamaConfiguration newValue) - : base(oldValue, newValue) - { - ModelName = BuildConfiguration.Combine(oldValue.ModelName, newValue.ModelName); - Schema = BuildConfiguration.Combine(oldValue.Schema, newValue.Schema); - HostName = BuildConfiguration.Combine(oldValue.HostName, newValue.HostName); - Port = BuildConfiguration.Combine(oldValue.Port, newValue.Port); - } + /// + /// Initializes a new instance of the class. + /// + /// The old Docker resource configuration. + /// The new Docker resource configuration. + public OllamaConfiguration(OllamaConfiguration oldValue, OllamaConfiguration newValue) + : base(oldValue, newValue) + { + ModelName = BuildConfiguration.Combine(oldValue.ModelName, newValue.ModelName); + } - public string ModelName { get; set; } = OllamaModels.Llama2; - public string Schema { get; set; } = "http"; - public string HostName { get; set; } = "localhost"; - public int Port { get; set; } = 11434; + /// + /// Name of the model to use. + /// + public string ModelName { get; set; } = OllamaModels.Llama2; - /// - /// Gets the name of the Docker image to use. - /// - public string ImageName { get; } = "ollama/ollama:latest"; + /// + /// Gets the default port of the Ollama API. + /// + public const int DefaultPort = 11434; + + /// + /// Default image name. + /// + public const string ImageName = "ollama/ollama:latest"; + + /// + /// Default volume path. + /// + public const string DefaultVolumePath = "/root/.ollama"; + + /// + /// Default volume name. + /// + public const string DefaultVolumeName = "ollama-volume"; + } } \ No newline at end of file diff --git a/src/Testcontainers.Ollama/OllamaContainer.cs b/src/Testcontainers.Ollama/OllamaContainer.cs index 6234cf574..826aceff1 100644 --- a/src/Testcontainers.Ollama/OllamaContainer.cs +++ b/src/Testcontainers.Ollama/OllamaContainer.cs @@ -1,37 +1,52 @@ -namespace Testcontainers.Ollama; - -/// -[PublicAPI] -public sealed class OllamaContainer : DockerContainer +namespace Testcontainers.Ollama { - /// - /// Initializes a new instance of the class. - /// - /// The container configuration. - /// The logger. - public OllamaContainer(OllamaConfiguration configuration, ILogger logger) - : base(configuration, logger) + /// + [PublicAPI] + public sealed class OllamaContainer : DockerContainer { - ModelName = configuration.ModelName; - Schema = configuration.Schema; - HostName = configuration.HostName; - Port = configuration.Port; - ImageName = configuration.ImageName; - } + /// + /// Initializes a new instance of the class. + /// + /// The container configuration. + /// The logger. + public OllamaContainer(OllamaConfiguration configuration, ILogger logger) + : base(configuration, logger) + { + ModelName = configuration.ModelName; + ImageName = OllamaConfiguration.ImageName; + } + + /// + /// Starts the Ollama container. + /// + public async Task StartOllamaAsync() + { + if (State!= TestcontainersStates.Created && State != TestcontainersStates.Running) { + throw new InvalidOperationException("Cannot start a container that has not been created."); + } + Task.WaitAll(ExecAsync(new List() + { + "ollama", "run", ModelName, + })); + + await Task.CompletedTask; + } - public string GetBaseUrl() => $"{Schema}://{HostName}:{Port}/api"; - - public string Schema { get; } - public string HostName { get; } - public int Port { get; } + /// + /// Gets the base URL of the Ollama API. + /// + /// The base URL of the Ollama API. + /// http://localhost:5000/api + public string GetBaseUrl() => $"http://{Hostname}:{GetMappedPublicPort(OllamaConfiguration.DefaultPort)}/api"; - /// - /// Gets the name of the Docker image to use. - /// - public string ImageName { get; } + /// + /// Gets the name of the Docker image to use. + /// + public string ImageName { get; } - /// - /// Gets the name of the model to run. - /// - public string ModelName { get; } + /// + /// Gets the name of the model to run. + /// + public string ModelName { get; } + } } \ No newline at end of file diff --git a/src/Testcontainers.Ollama/Usings.cs b/src/Testcontainers.Ollama/Usings.cs index a0845cb29..13053db61 100644 --- a/src/Testcontainers.Ollama/Usings.cs +++ b/src/Testcontainers.Ollama/Usings.cs @@ -6,6 +6,6 @@ global using JetBrains.Annotations; global using Microsoft.Extensions.Logging; global using DotNet.Testcontainers.Images; -global using System.Linq; -global using System.Threading.Tasks; -global using System; \ No newline at end of file +global using System; +global using System.Collections.Generic; +global using System.Threading.Tasks; \ No newline at end of file diff --git a/tests/Testcontainers.Ollama.Tests/OllamaContainerTests.cs b/tests/Testcontainers.Ollama.Tests/OllamaContainerTests.cs index c0c602310..55641c4ec 100644 --- a/tests/Testcontainers.Ollama.Tests/OllamaContainerTests.cs +++ b/tests/Testcontainers.Ollama.Tests/OllamaContainerTests.cs @@ -1,47 +1,49 @@ -namespace Testcontainers.Ollama.Tests; - -public class OllamaContainerTests : IAsyncLifetime +namespace Testcontainers.Ollama.Tests { - private readonly ITestOutputHelper _testOutputHelper; - private OllamaContainer _ollamaContainer; - - public OllamaContainerTests(ITestOutputHelper testOutputHelper) - { - _testOutputHelper = testOutputHelper; - } - - public async Task InitializeAsync() - { - TestcontainersSettings.Logger = new TestOutputLogger(nameof(OllamaContainerTests), _testOutputHelper); - _ollamaContainer = new OllamaBuilder().Build(); - await _ollamaContainer.StartAsync(); - } - - public async Task DisposeAsync() - { - await _ollamaContainer.DisposeAsync().AsTask(); - } - - [Fact] - [Trait(nameof(DockerCli.DockerPlatform), nameof(DockerCli.DockerPlatform.Linux))] - public async Task OllamaContainerReturnsSuccessful() + public class OllamaContainerTests : IAsyncLifetime { - var client = new OllamaApiClient(_ollamaContainer.GetBaseUrl(), _ollamaContainer.ModelName); - - var chatRequest = new ChatRequest() { - Model = _ollamaContainer.ModelName, - Stream = false, - Messages = new List() - { - new Message() { Content = "You are very helpful", Role = ChatRole.System }, - new Message() { Content = "Hello", Role = ChatRole.User }, - } - }; - - var response = await client.SendChat(chatRequest, stream => { }); - _testOutputHelper.WriteJson(response); - - Assert.True(response.Any()); + private readonly ITestOutputHelper _testOutputHelper; + private OllamaContainer _ollamaContainer; + + public OllamaContainerTests(ITestOutputHelper testOutputHelper) + { + _testOutputHelper = testOutputHelper; + } + + public async Task InitializeAsync() + { + TestcontainersSettings.Logger = new TestOutputLogger(nameof(OllamaContainerTests), _testOutputHelper); + _ollamaContainer = new OllamaBuilder().Build(); + await _ollamaContainer.StartAsync(); + await _ollamaContainer.StartOllamaAsync(); + } + + public async Task DisposeAsync() + { + await _ollamaContainer.DisposeAsync().AsTask(); + } + + [Fact] + [Trait(nameof(DockerCli.DockerPlatform), nameof(DockerCli.DockerPlatform.Linux))] + public async Task OllamaContainerReturnsSuccessful() + { + var client = new OllamaApiClient(_ollamaContainer.GetBaseUrl(), _ollamaContainer.ModelName); + + var chatRequest = new ChatRequest() { + Model = _ollamaContainer.ModelName, + Stream = false, + Messages = new List() + { + new Message() { Content = "What is a name", Role = ChatRole.User }, + } + }; + + var response = await client.SendChat(chatRequest, stream => { }); + response = response.ToList(); + + _testOutputHelper.WriteJson(response); + + Assert.True(response.Any()); + } } - } From d1c1aaee090b8dcc36c257c53525124d21cf1f81 Mon Sep 17 00:00:00 2001 From: "Frank R. Haugen" Date: Thu, 1 Feb 2024 21:50:27 +0100 Subject: [PATCH 6/6] #1097 Update Ollama configuration and remove test helpers This commit updates the Ollama configuration to allow more customization options and removes unnecessary test helpers. The OllamaConfiguration class was refactored to provide more configurable parameters such as the VolumePath and VolumeName. Additionally, the TestOutputHelperExtensions and TestOutputLogger classes were deleted as they were not providing any significant value. --- src/Testcontainers.Ollama/OllamaBuilder.cs | 33 +++++++++++-- .../OllamaConfiguration.cs | 45 ++++++++--------- src/Testcontainers.Ollama/OllamaContainer.cs | 31 +++++++----- .../TestOutputHelperExtensions.cs | 22 --------- .../TestOutputLogger.cs | 49 ------------------- .../Testcontainers.Commons.csproj | 1 - .../OllamaContainerTests.cs | 15 ++---- tests/Testcontainers.Ollama.Tests/Usings.cs | 1 - 8 files changed, 73 insertions(+), 124 deletions(-) delete mode 100644 tests/Testcontainers.Commons/TestOutputHelperExtensions.cs delete mode 100644 tests/Testcontainers.Commons/TestOutputLogger.cs diff --git a/src/Testcontainers.Ollama/OllamaBuilder.cs b/src/Testcontainers.Ollama/OllamaBuilder.cs index 18672fd19..3a0323ee0 100644 --- a/src/Testcontainers.Ollama/OllamaBuilder.cs +++ b/src/Testcontainers.Ollama/OllamaBuilder.cs @@ -4,6 +4,31 @@ namespace Testcontainers.Ollama [PublicAPI] public sealed class OllamaBuilder : ContainerBuilder { + /// + /// Gets the default port of the Ollama API. + /// + public const int DefaultPort = 11434; + + /// + /// Default image name and version tag. + /// + public const string OllamaImage = "ollama/ollama:0.1.22"; + + /// + /// Default volume path. + /// + public const string DefaultVolumePath = "/root/.ollama"; + + /// + /// Default volume name. + /// + public const string DefaultVolumeName = "ollama-volume"; + + /// + /// The default model name for the OllamaBuilder. + /// + public const string DefaultModelName = OllamaModels.Llama2; + /// /// Initializes a new instance of the class. /// @@ -54,9 +79,9 @@ protected override void Validate() protected override OllamaBuilder Init() { return base.Init() - .WithImage(new DockerImage(OllamaConfiguration.ImageName)) - .WithPortBinding(OllamaConfiguration.DefaultPort, true) - .WithVolumeMount(OllamaConfiguration.DefaultVolumeName, OllamaConfiguration.DefaultVolumePath) + .WithImage(new DockerImage(OllamaImage)) + .WithPortBinding(DefaultPort, true) + .WithVolumeMount(DefaultVolumeName, DefaultVolumePath) ; } @@ -90,7 +115,7 @@ protected override OllamaBuilder Merge(OllamaConfiguration oldValue, OllamaConfi /// public OllamaBuilder WithModelName(string name) { - return Merge(DockerResourceConfiguration, new OllamaConfiguration(DockerResourceConfiguration) {ModelName = name}); + return Merge(DockerResourceConfiguration, new OllamaConfiguration(DockerResourceConfiguration, new OllamaConfiguration(modelName: name))); } } } \ No newline at end of file diff --git a/src/Testcontainers.Ollama/OllamaConfiguration.cs b/src/Testcontainers.Ollama/OllamaConfiguration.cs index d3eb7e544..52abab44f 100644 --- a/src/Testcontainers.Ollama/OllamaConfiguration.cs +++ b/src/Testcontainers.Ollama/OllamaConfiguration.cs @@ -5,15 +5,14 @@ namespace Testcontainers.Ollama public sealed class OllamaConfiguration : ContainerConfiguration { /// - /// Initializes a new instance of the class. + /// The OllamaConfiguration class represents the configuration for an Ollama container. /// - /// - /// - /// - /// - public OllamaConfiguration(string modelName = null, string schema = null, int? port = null) + public OllamaConfiguration(string modelName = null, string volumePath = null, string volumeName = null, int? port = null) { - ModelName = modelName; + ModelName = modelName ?? string.Empty; + VolumePath = volumePath ?? OllamaBuilder.DefaultVolumePath; + VolumeName = volumeName ?? OllamaBuilder.DefaultVolumeName; + Port = port ?? OllamaBuilder.DefaultPort; } /// @@ -55,31 +54,29 @@ public OllamaConfiguration(OllamaConfiguration oldValue, OllamaConfiguration new : base(oldValue, newValue) { ModelName = BuildConfiguration.Combine(oldValue.ModelName, newValue.ModelName); + VolumePath = BuildConfiguration.Combine(oldValue.VolumePath, newValue.VolumePath); + VolumeName = BuildConfiguration.Combine(oldValue.VolumeName, newValue.VolumeName); + Port = BuildConfiguration.Combine(oldValue.Port, newValue.Port); } - - /// - /// Name of the model to use. - /// - public string ModelName { get; set; } = OllamaModels.Llama2; - + /// - /// Gets the default port of the Ollama API. + /// Represents the configuration for the Ollama container. /// - public const int DefaultPort = 11434; - + public string ModelName { get; set; } + /// - /// Default image name. + /// The OllamaConfiguration class represents the configuration for an Ollama container. /// - public const string ImageName = "ollama/ollama:latest"; - + public string VolumePath { get; set; } + /// - /// Default volume path. + /// Gets or sets the name of the volume associated with the Ollama container. /// - public const string DefaultVolumePath = "/root/.ollama"; - + public string VolumeName { get; set; } + /// - /// Default volume name. + /// The class represents the configuration for an Ollama container port. /// - public const string DefaultVolumeName = "ollama-volume"; + public int Port { get; set; } } } \ No newline at end of file diff --git a/src/Testcontainers.Ollama/OllamaContainer.cs b/src/Testcontainers.Ollama/OllamaContainer.cs index 826aceff1..53113a052 100644 --- a/src/Testcontainers.Ollama/OllamaContainer.cs +++ b/src/Testcontainers.Ollama/OllamaContainer.cs @@ -1,3 +1,5 @@ +using System.Threading; + namespace Testcontainers.Ollama { /// @@ -12,24 +14,29 @@ public sealed class OllamaContainer : DockerContainer public OllamaContainer(OllamaConfiguration configuration, ILogger logger) : base(configuration, logger) { - ModelName = configuration.ModelName; - ImageName = OllamaConfiguration.ImageName; + Configuration = configuration; + } + + public OllamaConfiguration Configuration { get; private set; } + + public Task Run(CancellationToken ct = default) + { + return Run(Configuration.ModelName, ct); } /// /// Starts the Ollama container. /// - public async Task StartOllamaAsync() + public Task Run(string modelName, CancellationToken ct = default) { - if (State!= TestcontainersStates.Created && State != TestcontainersStates.Running) { - throw new InvalidOperationException("Cannot start a container that has not been created."); + ModelName = modelName; + if (State!= TestcontainersStates.Created && State != TestcontainersStates.Running) { + ThrowIfResourceNotFound(); } - Task.WaitAll(ExecAsync(new List() - { + + return ExecAsync(new List() { "ollama", "run", ModelName, - })); - - await Task.CompletedTask; + }, ct); } /// @@ -37,7 +44,7 @@ public async Task StartOllamaAsync() /// /// The base URL of the Ollama API. /// http://localhost:5000/api - public string GetBaseUrl() => $"http://{Hostname}:{GetMappedPublicPort(OllamaConfiguration.DefaultPort)}/api"; + public string GetBaseUrl() => $"http://{Hostname}:{GetMappedPublicPort(OllamaBuilder.DefaultPort)}/api"; /// /// Gets the name of the Docker image to use. @@ -47,6 +54,6 @@ public async Task StartOllamaAsync() /// /// Gets the name of the model to run. /// - public string ModelName { get; } + public string ModelName { get; private set; } } } \ No newline at end of file diff --git a/tests/Testcontainers.Commons/TestOutputHelperExtensions.cs b/tests/Testcontainers.Commons/TestOutputHelperExtensions.cs deleted file mode 100644 index 4dbb8f490..000000000 --- a/tests/Testcontainers.Commons/TestOutputHelperExtensions.cs +++ /dev/null @@ -1,22 +0,0 @@ -#nullable enable -using System.Text.Json; -using System.Text.Json.Serialization; -using Xunit.Abstractions; - -namespace DotNet.Testcontainers.Commons -{ - public static class TestOutputHelperExtensions - { - public static void WriteJson(this ITestOutputHelper testOutputHelper, T source, JsonSerializerOptions? jsonSerializerOptions = null) - { - jsonSerializerOptions ??= new JsonSerializerOptions - { - WriteIndented = true, - Converters = { new JsonStringEnumConverter()}, - MaxDepth = 64, - }; - var json = JsonSerializer.Serialize(source, jsonSerializerOptions); - testOutputHelper.WriteLine(json); - } - } -} \ No newline at end of file diff --git a/tests/Testcontainers.Commons/TestOutputLogger.cs b/tests/Testcontainers.Commons/TestOutputLogger.cs deleted file mode 100644 index 7796c31a2..000000000 --- a/tests/Testcontainers.Commons/TestOutputLogger.cs +++ /dev/null @@ -1,49 +0,0 @@ -using Microsoft.Extensions.Logging; -using Xunit.Abstractions; - -namespace DotNet.Testcontainers.Commons; - -public class TestOutputLogger : ILogger -{ - private readonly string _categoryName; - private readonly LogLevel _logLevel; - private readonly ITestOutputHelper _testOutputHelper; - - public TestOutputLogger(string categoryName, ITestOutputHelper testOutputHelper, LogLevel logLevel = LogLevel.Information) - { - _categoryName = categoryName; - _testOutputHelper = testOutputHelper; - _logLevel = logLevel; - } - - /// - public void Log(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func formatter) - { - if (!IsEnabled(logLevel)) - return; - - if (formatter == null) - throw new ArgumentNullException(nameof(formatter)); - - var message = formatter(state, exception); - if (string.IsNullOrEmpty(message)) - { - return; - } - - _testOutputHelper.WriteLine($"{logLevel}: {_categoryName}: {message}"); - } - - /// - public bool IsEnabled(LogLevel logLevel) - { - return logLevel >= _logLevel; - } - - /// - public IDisposable BeginScope(TState state) - { - return null!; - } - -} \ No newline at end of file diff --git a/tests/Testcontainers.Commons/Testcontainers.Commons.csproj b/tests/Testcontainers.Commons/Testcontainers.Commons.csproj index 4810e26a0..0fce12a00 100644 --- a/tests/Testcontainers.Commons/Testcontainers.Commons.csproj +++ b/tests/Testcontainers.Commons/Testcontainers.Commons.csproj @@ -8,7 +8,6 @@ - diff --git a/tests/Testcontainers.Ollama.Tests/OllamaContainerTests.cs b/tests/Testcontainers.Ollama.Tests/OllamaContainerTests.cs index 55641c4ec..e9a9f7b39 100644 --- a/tests/Testcontainers.Ollama.Tests/OllamaContainerTests.cs +++ b/tests/Testcontainers.Ollama.Tests/OllamaContainerTests.cs @@ -2,20 +2,15 @@ namespace Testcontainers.Ollama.Tests { public class OllamaContainerTests : IAsyncLifetime { - private readonly ITestOutputHelper _testOutputHelper; private OllamaContainer _ollamaContainer; - public OllamaContainerTests(ITestOutputHelper testOutputHelper) - { - _testOutputHelper = testOutputHelper; - } - public async Task InitializeAsync() { - TestcontainersSettings.Logger = new TestOutputLogger(nameof(OllamaContainerTests), _testOutputHelper); - _ollamaContainer = new OllamaBuilder().Build(); + _ollamaContainer = new OllamaBuilder() + .OllamaConfig(new OllamaConfiguration(OllamaModels.Llama2)) + .Build(); await _ollamaContainer.StartAsync(); - await _ollamaContainer.StartOllamaAsync(); + await _ollamaContainer.Run(); } public async Task DisposeAsync() @@ -41,8 +36,6 @@ public async Task OllamaContainerReturnsSuccessful() var response = await client.SendChat(chatRequest, stream => { }); response = response.ToList(); - _testOutputHelper.WriteJson(response); - Assert.True(response.Any()); } } diff --git a/tests/Testcontainers.Ollama.Tests/Usings.cs b/tests/Testcontainers.Ollama.Tests/Usings.cs index e8ee5c203..e610c15c9 100644 --- a/tests/Testcontainers.Ollama.Tests/Usings.cs +++ b/tests/Testcontainers.Ollama.Tests/Usings.cs @@ -1,7 +1,6 @@ global using System.Threading.Tasks; global using DotNet.Testcontainers.Commons; global using Xunit; -global using Xunit.Abstractions; global using System.Collections.Generic; global using System.Linq; global using DotNet.Testcontainers.Configurations;