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