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());
+ }
}
-
}