From 94126733dd9915b4a9b857386f1d925cf606b438 Mon Sep 17 00:00:00 2001
From: Andre Hofmeister <9199345+HofmeisterAn@users.noreply.github.com>
Date: Thu, 26 Jan 2023 13:21:21 +0100
Subject: [PATCH] feat(#493): Add .NET module template (#742)
---
Directory.Build.props | 2 +-
LICENSE | 2 +-
README.md | 2 +-
docs/index.md | 2 +-
.../CSharp/.template.config/template.json | 44 ++++++++++
.../ModuleNameBuilder.cs | 86 +++++++++++++++++++
.../ModuleNameConfiguration.cs | 62 +++++++++++++
.../ModuleNameContainer.cs | 16 ++++
.../Testcontainers.ModuleName.csproj | 12 +++
.../Testcontainers.ModuleName/Usings.cs | 6 ++
src/Templates/FSharp/.gitkeep | 0
src/Templates/README.md | 3 +
src/Templates/VisualBasic/.gitkeep | 0
...tractBuilder`2.cs => AbstractBuilder`4.cs} | 0
.../Builders/BuildConfiguration.cs | 2 +-
.../Builders/ContainerBuilder.cs | 2 +-
...ractBuilder`2.cs => IAbstractBuilder`3.cs} | 1 +
17 files changed, 236 insertions(+), 6 deletions(-)
create mode 100644 src/Templates/CSharp/.template.config/template.json
create mode 100644 src/Templates/CSharp/Testcontainers.ModuleName/ModuleNameBuilder.cs
create mode 100644 src/Templates/CSharp/Testcontainers.ModuleName/ModuleNameConfiguration.cs
create mode 100644 src/Templates/CSharp/Testcontainers.ModuleName/ModuleNameContainer.cs
create mode 100644 src/Templates/CSharp/Testcontainers.ModuleName/Testcontainers.ModuleName.csproj
create mode 100644 src/Templates/CSharp/Testcontainers.ModuleName/Usings.cs
create mode 100644 src/Templates/FSharp/.gitkeep
create mode 100644 src/Templates/README.md
create mode 100644 src/Templates/VisualBasic/.gitkeep
rename src/Testcontainers/Builders/{AbstractBuilder`2.cs => AbstractBuilder`4.cs} (100%)
rename src/Testcontainers/Builders/{IAbstractBuilder`2.cs => IAbstractBuilder`3.cs} (97%)
diff --git a/Directory.Build.props b/Directory.Build.props
index 2fdba4d9c..9baee864c 100644
--- a/Directory.Build.props
+++ b/Directory.Build.props
@@ -9,7 +9,7 @@
$(Version)
$(Version)
Testcontainers
- Copyright (c) 2019 - 2022 Andre Hofmeister and other authors
+ Copyright (c) 2019 - 2023 Andre Hofmeister and other authors
Andre Hofmeister and contributors
Andre Hofmeister
Testcontainers for .NET is a library to support tests with throwaway instances of Docker containers for all compatible .NET Standard versions.
diff --git a/LICENSE b/LICENSE
index 743cc9bff..83918c3a7 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,6 +1,6 @@
The MIT License (MIT)
-Copyright (c) 2019 - 2022 Andre Hofmeister and other authors
+Copyright (c) 2019 - 2023 Andre Hofmeister and other authors
Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in
diff --git a/README.md b/README.md
index 9644266df..80bd3fc46 100644
--- a/README.md
+++ b/README.md
@@ -19,7 +19,7 @@ See [LICENSE](https://github.com/testcontainers/testcontainers-dotnet/blob/maste
## Copyright
-Copyright (c) 2019 - 2022 Andre Hofmeister and other authors.
+Copyright (c) 2019 - 2023 Andre Hofmeister and other authors.
See [contributors][testcontainers-dotnet-contributors] for all contributors.
diff --git a/docs/index.md b/docs/index.md
index 44a3ccef6..a533a7506 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -50,7 +50,7 @@ See [LICENSE](https://raw.githubusercontent.com/testcontainers/testcontainers-do
## Copyright
-Copyright (c) 2019 - 2022 Andre Hofmeister and other authors.
+Copyright (c) 2019 - 2023 Andre Hofmeister and other authors.
See [contributors][testcontainers-dotnet-contributors] for all contributors.
diff --git a/src/Templates/CSharp/.template.config/template.json b/src/Templates/CSharp/.template.config/template.json
new file mode 100644
index 000000000..2c9586a59
--- /dev/null
+++ b/src/Templates/CSharp/.template.config/template.json
@@ -0,0 +1,44 @@
+{
+ "$schema": "http://json.schemastore.org/template",
+ "author": "Andre Hofmeister and contributors",
+ "description": "A .NET template to scaffold advanced Testcontainers for .NET modules.",
+ "classifications": ["Test", "Testcontainers"],
+ "groupIdentity": "Testcontainers",
+ "identity": "Testcontainers.Module.CSharp",
+ "name": "Testcontainers Module Project",
+ "shortName": "tcm",
+ "sourceName": "ModuleName",
+ "symbols": {
+ "official-module": {
+ "type": "parameter",
+ "datatype": "bool",
+ "defaultValue": "false",
+ "description": "Determines whether the template generates an official module or not."
+ },
+ "official-module-prefix": {
+ "type": "generated",
+ "datatype": "text",
+ "generator": "switch",
+ "fileRename": "Testcontainers.",
+ "replaces": "Testcontainers.",
+ "parameters": {
+ "cases": [
+ {
+ "condition": "official-module",
+ "value": "Testcontainers.",
+ "description": "Keep the Testcontainers official module prefix."
+ }
+ ]
+ },
+ "onlyIf": [
+ {
+ "after": "namespace "
+ }
+ ]
+ }
+ },
+ "tags": {
+ "language": "C#",
+ "type": "project"
+ }
+}
\ No newline at end of file
diff --git a/src/Templates/CSharp/Testcontainers.ModuleName/ModuleNameBuilder.cs b/src/Templates/CSharp/Testcontainers.ModuleName/ModuleNameBuilder.cs
new file mode 100644
index 000000000..e0f4db0ee
--- /dev/null
+++ b/src/Templates/CSharp/Testcontainers.ModuleName/ModuleNameBuilder.cs
@@ -0,0 +1,86 @@
+namespace Testcontainers.ModuleName;
+
+///
+[PublicAPI]
+public sealed class ModuleNameBuilder : ContainerBuilder
+{
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public ModuleNameBuilder()
+ : this(new ModuleNameConfiguration())
+ {
+ // 1) To change the ContainerBuilder default configuration override the DockerResourceConfiguration property and the "ModuleNameBuilder 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 "ModuleNameBuilder WithModuleNameConfig(object)".
+ // Merge the current module configuration with a new instance of the immutable ModuleNameConfiguration type to update the module configuration.
+
+ // DockerResourceConfiguration = Init().DockerResourceConfiguration;
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The Docker resource configuration.
+ private ModuleNameBuilder(ModuleNameConfiguration resourceConfiguration)
+ : base(resourceConfiguration)
+ {
+ // DockerResourceConfiguration = resourceConfiguration;
+ }
+
+ // ///
+ // protected override ModuleNameConfiguration DockerResourceConfiguration { get; }
+
+ // ///
+ // /// Sets the ModuleName config.
+ // ///
+ // /// The ModuleName config.
+ // /// A configured instance of .
+ // public ModuleNameBuilder WithModuleNameConfig(object config)
+ // {
+ // // Extends the ContainerBuilder capabilities and holds a custom configuration in ModuleNameConfiguration.
+ // // In case of a module requires other properties to represent itself, extend ContainerConfiguration.
+ // return Merge(DockerResourceConfiguration, new ModuleNameConfiguration(config: config));
+ // }
+
+ ///
+ public override ModuleNameContainer Build()
+ {
+ Validate();
+ return new ModuleNameContainer(DockerResourceConfiguration, TestcontainersSettings.Logger);
+ }
+
+ // ///
+ // protected override ModuleNameBuilder Init()
+ // {
+ // return base.Init();
+ // }
+
+ // ///
+ // protected override void Validate()
+ // {
+ // base.Validate();
+ // }
+
+ ///
+ protected override ModuleNameBuilder Clone(IResourceConfiguration resourceConfiguration)
+ {
+ return Merge(DockerResourceConfiguration, new ModuleNameConfiguration(resourceConfiguration));
+ }
+
+ ///
+ protected override ModuleNameBuilder Clone(IContainerConfiguration resourceConfiguration)
+ {
+ return Merge(DockerResourceConfiguration, new ModuleNameConfiguration(resourceConfiguration));
+ }
+
+ ///
+ protected override ModuleNameBuilder Merge(ModuleNameConfiguration oldValue, ModuleNameConfiguration newValue)
+ {
+ return new ModuleNameBuilder(new ModuleNameConfiguration(oldValue, newValue));
+ }
+}
\ No newline at end of file
diff --git a/src/Templates/CSharp/Testcontainers.ModuleName/ModuleNameConfiguration.cs b/src/Templates/CSharp/Testcontainers.ModuleName/ModuleNameConfiguration.cs
new file mode 100644
index 000000000..1b84aa6db
--- /dev/null
+++ b/src/Templates/CSharp/Testcontainers.ModuleName/ModuleNameConfiguration.cs
@@ -0,0 +1,62 @@
+namespace Testcontainers.ModuleName;
+
+///
+[PublicAPI]
+public sealed class ModuleNameConfiguration : ContainerConfiguration
+{
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public ModuleNameConfiguration(object config = null)
+ {
+ // // Sets the custom builder methods property values.
+ // Config = config;
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The Docker resource configuration.
+ public ModuleNameConfiguration(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 ModuleNameConfiguration(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 ModuleNameConfiguration(ModuleNameConfiguration resourceConfiguration)
+ : this(new ModuleNameConfiguration(), 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 ModuleNameConfiguration(ModuleNameConfiguration oldValue, ModuleNameConfiguration newValue)
+ : base(oldValue, newValue)
+ {
+ // // Create an updated immutable copy of the module configuration.
+ // Config = BuildConfiguration.Combine(oldValue.Config, newValue.Config);
+ }
+
+ // ///
+ // /// Gets the ModuleName config.
+ // ///
+ // public object Config { get; }
+}
\ No newline at end of file
diff --git a/src/Templates/CSharp/Testcontainers.ModuleName/ModuleNameContainer.cs b/src/Templates/CSharp/Testcontainers.ModuleName/ModuleNameContainer.cs
new file mode 100644
index 000000000..5bb59e623
--- /dev/null
+++ b/src/Templates/CSharp/Testcontainers.ModuleName/ModuleNameContainer.cs
@@ -0,0 +1,16 @@
+namespace Testcontainers.ModuleName;
+
+///
+[PublicAPI]
+public sealed class ModuleNameContainer : DockerContainer
+{
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The container configuration.
+ /// The logger.
+ public ModuleNameContainer(IContainerConfiguration configuration, ILogger logger)
+ : base(configuration, logger)
+ {
+ }
+}
\ No newline at end of file
diff --git a/src/Templates/CSharp/Testcontainers.ModuleName/Testcontainers.ModuleName.csproj b/src/Templates/CSharp/Testcontainers.ModuleName/Testcontainers.ModuleName.csproj
new file mode 100644
index 000000000..37a1be0f7
--- /dev/null
+++ b/src/Templates/CSharp/Testcontainers.ModuleName/Testcontainers.ModuleName.csproj
@@ -0,0 +1,12 @@
+
+
+ netstandard2.0;netstandard2.1
+ latest
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/Templates/CSharp/Testcontainers.ModuleName/Usings.cs b/src/Templates/CSharp/Testcontainers.ModuleName/Usings.cs
new file mode 100644
index 000000000..238dcb1c1
--- /dev/null
+++ b/src/Templates/CSharp/Testcontainers.ModuleName/Usings.cs
@@ -0,0 +1,6 @@
+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;
\ No newline at end of file
diff --git a/src/Templates/FSharp/.gitkeep b/src/Templates/FSharp/.gitkeep
new file mode 100644
index 000000000..e69de29bb
diff --git a/src/Templates/README.md b/src/Templates/README.md
new file mode 100644
index 000000000..d27fc23fa
--- /dev/null
+++ b/src/Templates/README.md
@@ -0,0 +1,3 @@
+# .NET module template
+
+The .NET module template scaffolds Testcontainers for .NET modules. While simple modules can inherit from `ContainerBuilder`, more advanced modules usually require additional properties and methods to set up a running configuration. To scaffold a new module, install the template `dotnet new install ./src/Templates` and run `dotnet new tcm --name ${module_name} ----output ${output_directory}`.
diff --git a/src/Templates/VisualBasic/.gitkeep b/src/Templates/VisualBasic/.gitkeep
new file mode 100644
index 000000000..e69de29bb
diff --git a/src/Testcontainers/Builders/AbstractBuilder`2.cs b/src/Testcontainers/Builders/AbstractBuilder`4.cs
similarity index 100%
rename from src/Testcontainers/Builders/AbstractBuilder`2.cs
rename to src/Testcontainers/Builders/AbstractBuilder`4.cs
diff --git a/src/Testcontainers/Builders/BuildConfiguration.cs b/src/Testcontainers/Builders/BuildConfiguration.cs
index 9748cb657..5a08993d4 100644
--- a/src/Testcontainers/Builders/BuildConfiguration.cs
+++ b/src/Testcontainers/Builders/BuildConfiguration.cs
@@ -3,7 +3,7 @@ namespace DotNet.Testcontainers.Builders
using System.Collections.Generic;
using System.Linq;
- internal static class BuildConfiguration
+ public static class BuildConfiguration
{
///
/// Returns the changed configuration object. If there is no change, the previous configuration object is returned.
diff --git a/src/Testcontainers/Builders/ContainerBuilder.cs b/src/Testcontainers/Builders/ContainerBuilder.cs
index fbae0aeb9..3fe591780 100644
--- a/src/Testcontainers/Builders/ContainerBuilder.cs
+++ b/src/Testcontainers/Builders/ContainerBuilder.cs
@@ -41,7 +41,7 @@ public ContainerBuilder()
/// Initializes a new instance of the class.
///
/// The Docker resource configuration.
- private ContainerBuilder(IContainerConfiguration dockerResourceConfiguration)
+ protected ContainerBuilder(IContainerConfiguration dockerResourceConfiguration)
: base(dockerResourceConfiguration)
{
this.DockerResourceConfiguration = dockerResourceConfiguration;
diff --git a/src/Testcontainers/Builders/IAbstractBuilder`2.cs b/src/Testcontainers/Builders/IAbstractBuilder`3.cs
similarity index 97%
rename from src/Testcontainers/Builders/IAbstractBuilder`2.cs
rename to src/Testcontainers/Builders/IAbstractBuilder`3.cs
index b9d6d7769..aab2c769e 100644
--- a/src/Testcontainers/Builders/IAbstractBuilder`2.cs
+++ b/src/Testcontainers/Builders/IAbstractBuilder`3.cs
@@ -88,6 +88,7 @@ public interface IAbstractBuilder with the given resource configuration.
///
/// A configured instance of .
+ /// Thrown when a mandatory Docker resource configuration is not set.
[PublicAPI]
TResourceEntity Build();
}