Port legacy Stubble template engine [#2]
This commit is contained in:
Родитель
26fe75ea15
Коммит
750c45f345
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"version": 1,
|
||||
"isRoot": true,
|
||||
"tools": {
|
||||
"dotnet-reportgenerator-globaltool": {
|
||||
"version": "4.6.4",
|
||||
"commands": [
|
||||
"reportgenerator"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
|
@ -7,10 +7,10 @@ insert_final_newline = true
|
|||
max_line_length = 120
|
||||
charset = utf-8
|
||||
|
||||
[*.cs]
|
||||
indent_size = 4
|
||||
[*.{csproj,props,targets,DotSettings}]
|
||||
indent_size = 2
|
||||
|
||||
[*.{xml,csproj,props}]
|
||||
[*.cs]
|
||||
indent_size = 4
|
||||
|
||||
[*.yaml]
|
||||
|
@ -18,3 +18,6 @@ indent_size = 2
|
|||
|
||||
[*.ps1]
|
||||
indent_size = 4
|
||||
|
||||
[*.json]
|
||||
indent_size = 2
|
||||
|
|
|
@ -1,8 +1,12 @@
|
|||
<Project>
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
<Target Name="CleanBaseOutput" AfterTargets="Clean">
|
||||
<RemoveDir Directories="$(BaseOutputPath)" />
|
||||
</Target>
|
||||
|
||||
</Project>
|
||||
|
|
|
@ -6,7 +6,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Steeltoe.InitializrApi", "s
|
|||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Steeltoe.InitializrApi.Models", "src\InitializrApi.Models\Steeltoe.InitializrApi.Models.csproj", "{ACE6FEE1-9CEA-4A95-9D76-C62A41947C8F}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Steeltoe.InitializrApi.Test", "test\InitializrApi.Test\Steeltoe.InitializrApi.Test.csproj", "{EA849C8F-7118-45DB-BBF2-D36CE1FD43B4}"
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Steeltoe.InitializrApi.Test.Utils", "test\InitializrApi.Test.Utils\Steeltoe.InitializrApi.Test.Utils.csproj", "{EC08DC14-11D5-40D3-8908-BDB0D789F48D}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Steeltoe.InitializrApi.Test.Unit", "test\InitializrApi.Test.Unit\Steeltoe.InitializrApi.Test.Unit.csproj", "{EA849C8F-7118-45DB-BBF2-D36CE1FD43B4}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Steeltoe.InitializrApi.Test.Integration", "test\InitializrApi.Test.Integration\Steeltoe.InitializrApi.Test.Integration.csproj", "{24A2AB13-F4C4-4C88-B67D-D280610240B8}"
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{F80B44AC-7383-40DA-B353-16163BF279F1}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
|
@ -69,6 +73,30 @@ Global
|
|||
{EA849C8F-7118-45DB-BBF2-D36CE1FD43B4}.Release|x64.Build.0 = Release|Any CPU
|
||||
{EA849C8F-7118-45DB-BBF2-D36CE1FD43B4}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{EA849C8F-7118-45DB-BBF2-D36CE1FD43B4}.Release|x86.Build.0 = Release|Any CPU
|
||||
{24A2AB13-F4C4-4C88-B67D-D280610240B8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{24A2AB13-F4C4-4C88-B67D-D280610240B8}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{24A2AB13-F4C4-4C88-B67D-D280610240B8}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{24A2AB13-F4C4-4C88-B67D-D280610240B8}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{24A2AB13-F4C4-4C88-B67D-D280610240B8}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{24A2AB13-F4C4-4C88-B67D-D280610240B8}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{24A2AB13-F4C4-4C88-B67D-D280610240B8}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{24A2AB13-F4C4-4C88-B67D-D280610240B8}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{24A2AB13-F4C4-4C88-B67D-D280610240B8}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{24A2AB13-F4C4-4C88-B67D-D280610240B8}.Release|x64.Build.0 = Release|Any CPU
|
||||
{24A2AB13-F4C4-4C88-B67D-D280610240B8}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{24A2AB13-F4C4-4C88-B67D-D280610240B8}.Release|x86.Build.0 = Release|Any CPU
|
||||
{EC08DC14-11D5-40D3-8908-BDB0D789F48D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{EC08DC14-11D5-40D3-8908-BDB0D789F48D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{EC08DC14-11D5-40D3-8908-BDB0D789F48D}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||
{EC08DC14-11D5-40D3-8908-BDB0D789F48D}.Debug|x64.Build.0 = Debug|Any CPU
|
||||
{EC08DC14-11D5-40D3-8908-BDB0D789F48D}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||
{EC08DC14-11D5-40D3-8908-BDB0D789F48D}.Debug|x86.Build.0 = Debug|Any CPU
|
||||
{EC08DC14-11D5-40D3-8908-BDB0D789F48D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{EC08DC14-11D5-40D3-8908-BDB0D789F48D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{EC08DC14-11D5-40D3-8908-BDB0D789F48D}.Release|x64.ActiveCfg = Release|Any CPU
|
||||
{EC08DC14-11D5-40D3-8908-BDB0D789F48D}.Release|x64.Build.0 = Release|Any CPU
|
||||
{EC08DC14-11D5-40D3-8908-BDB0D789F48D}.Release|x86.ActiveCfg = Release|Any CPU
|
||||
{EC08DC14-11D5-40D3-8908-BDB0D789F48D}.Release|x86.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
|
|
@ -1,4 +1,8 @@
|
|||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Initializr/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Steeltoe/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Initializr/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Steeltoe/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:String x:Key="/Default/CodeStyle/FileHeader/FileHeaderText/@EntryValue">Licensed to the .NET Foundation under one or more agreements.
|
||||
The .NET Foundation licenses this file to you under the Apache 2.0 License.
|
||||
See the LICENSE file in the project root for more information.
|
||||
</s:String>
|
||||
</wpf:ResourceDictionary>
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
# InitializrApi
|
||||
# Steeltoe InitializrApi
|
||||
|
||||
Steeltoe Initializr API reference implementation
|
||||
|
||||
[![Build Status](https://dev.azure.com/SteeltoeOSS/Steeltoe/_apis/build/status/Initializr/SteeltoeOSS.InitializrApi?branchName=master)](https://dev.azure.com/SteeltoeOSS/Steeltoe/_build/latest?definitionId=31&branchName=master)
|
||||
|
|
|
@ -1,28 +1,24 @@
|
|||
<Project>
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworkMonikerAssemblyAttributesPath>$([System.IO.Path]::Combine('$(IntermediateOutputPath)','$(TargetFrameworkMoniker).AssemblyAttributes$(DefaultLanguageSourceExtension)'))</TargetFrameworkMonikerAssemblyAttributesPath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<TargetFrameworkMonikerAssemblyAttributesPath>$([System.IO.Path]::Combine('$(IntermediateOutputPath)','$(TargetFrameworkMoniker).AssemblyAttributes$(DefaultLanguageSourceExtension)'))</TargetFrameworkMonikerAssemblyAttributesPath>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<EmbeddedFiles Include="$(GeneratedAssemblyInfoFile)"/>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<EmbeddedFiles Include="$(GeneratedAssemblyInfoFile)" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<SourceRoot Include="$(NuGetPackageRoot)" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<SourceRoot Include="$(NuGetPackageRoot)" />
|
||||
</ItemGroup>
|
||||
|
||||
<Target Name="CoverletGetPathMap"
|
||||
DependsOnTargets="InitializeSourceRootMappedPaths"
|
||||
Returns="@(_LocalTopLevelSourceRoot)"
|
||||
Condition="'$(DeterministicSourcePaths)' == 'true'">
|
||||
<ItemGroup>
|
||||
<_LocalTopLevelSourceRoot Include="@(SourceRoot)" Condition="'%(SourceRoot.NestedRoot)' == ''"/>
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
<Target Name="CoverletGetPathMap"
|
||||
DependsOnTargets="InitializeSourceRootMappedPaths"
|
||||
Returns="@(_LocalTopLevelSourceRoot)"
|
||||
Condition="'$(DeterministicSourcePaths)' == 'true'">
|
||||
<ItemGroup>
|
||||
<_LocalTopLevelSourceRoot Include="@(SourceRoot)" Condition="'%(SourceRoot.NestedRoot)' == ''" />
|
||||
</ItemGroup>
|
||||
</Target>
|
||||
|
||||
</Project>
|
||||
|
||||
<!--
|
||||
vim: ft=xml
|
||||
-->
|
||||
|
|
|
@ -1,41 +1,37 @@
|
|||
<Project>
|
||||
|
||||
<Import Project="$([MSBuild]::GetPathOfFileAbove('Directory.Build.props', '$(MSBuildThisFileDirectory)../'))" />
|
||||
<Import Project="$([MSBuild]::GetPathOfFileAbove('Directory.Build.props', '$(MSBuildThisFileDirectory)../'))" />
|
||||
|
||||
<PropertyGroup>
|
||||
<Authors>Steeltoe,VMware</Authors>
|
||||
<PublishRepositoryUrl>true</PublishRepositoryUrl>
|
||||
<IncludeSymbols>true</IncludeSymbols>
|
||||
<EmbedUntrackedSources>true</EmbedUntrackedSources>
|
||||
<AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<Authors>Steeltoe,VMware</Authors>
|
||||
<PublishRepositoryUrl>true</PublishRepositoryUrl>
|
||||
<IncludeSymbols>true</IncludeSymbols>
|
||||
<EmbedUntrackedSources>true</EmbedUntrackedSources>
|
||||
<AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<!-- SA1101: Prefix local calls with this -->
|
||||
<!-- SA1309: Field '...' should not begin with an underscore -->
|
||||
<NoWarn>SA1101;SA1309</NoWarn>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<!-- SA1101: Prefix local calls with this -->
|
||||
<!-- SA1309: Field '...' should not begin with an underscore -->
|
||||
<NoWarn>SA1101;SA1309</NoWarn>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<Version Condition=" '$(BUILD_BUILDNUMBER)' == '' ">0.7.0</Version>
|
||||
<Version Condition=" '$(BUILD_BUILDNUMBER)' != '' ">$(BUILD_BUILDNUMBER)</Version>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<Version Condition=" '$(BUILD_BUILDNUMBER)' == '' ">0.7.0</Version>
|
||||
<Version Condition=" '$(BUILD_BUILDNUMBER)' != '' ">$(BUILD_BUILDNUMBER)</Version>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(TF_BUILD)' == 'true'">
|
||||
<ContinuousIntegrationBuild>true</ContinuousIntegrationBuild>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(TF_BUILD)' == 'true'">
|
||||
<ContinuousIntegrationBuild>true</ContinuousIntegrationBuild>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All"/>
|
||||
<PackageReference Include="StyleCop.Analyzers" Version="1.1.118">
|
||||
<PrivateAssets>All</PrivateAssets>
|
||||
</PackageReference>
|
||||
<AdditionalFiles Include="$(MSBuildThisFileDirectory)\..\stylecop.json" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" />
|
||||
<PackageReference Include="StyleCop.Analyzers" Version="1.1.118">
|
||||
<PrivateAssets>All</PrivateAssets>
|
||||
</PackageReference>
|
||||
<AdditionalFiles Include="$(MSBuildThisFileDirectory)\..\stylecop.json" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
<!--
|
||||
vim: ft=xml
|
||||
-->
|
||||
|
|
|
@ -5,10 +5,14 @@
|
|||
namespace Steeltoe.InitializrApi.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// A model of project configuration metadata used by Initializr UIs and clients.
|
||||
/// A model of metadata used to describe the configuration of a project.
|
||||
/// </summary>
|
||||
public sealed class ProjectMetadata
|
||||
{
|
||||
/* ----------------------------------------------------------------- *
|
||||
* properties *
|
||||
* ----------------------------------------------------------------- */
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the project name.
|
||||
/// </summary>
|
||||
|
@ -19,30 +23,35 @@ namespace Steeltoe.InitializrApi.Models
|
|||
/// </summary>
|
||||
public Text Description { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the project namespace.
|
||||
/// </summary>
|
||||
public Text Namespace { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Steeltoe versions.
|
||||
/// </summary>
|
||||
public SingleSelectList SteeltoeVersion { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the DotNet framework versions.
|
||||
/// Gets or sets the DotNet frameworks.
|
||||
/// </summary>
|
||||
public SingleSelectList DotNetVersion { get; set; }
|
||||
public SingleSelectList DotNetFramework { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the DotNet template types.
|
||||
/// </summary>
|
||||
public SingleSelectList Type { get; set; }
|
||||
public SingleSelectList DotNetTemplate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the DotNet languages.
|
||||
/// Gets or sets the languages.
|
||||
/// </summary>
|
||||
public SingleSelectList Language { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the project bundle archive format.
|
||||
/// Gets or sets the project archive mime type.
|
||||
/// </summary>
|
||||
public SingleSelectList Format { get; set; }
|
||||
public SingleSelectList ArchiveMimeType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the project dependencies.
|
||||
|
@ -70,8 +79,6 @@ namespace Steeltoe.InitializrApi.Models
|
|||
/// </summary>
|
||||
public abstract class Item
|
||||
{
|
||||
private string _name;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the item ID.
|
||||
/// </summary>
|
||||
|
@ -80,11 +87,7 @@ namespace Steeltoe.InitializrApi.Models
|
|||
/// <summary>
|
||||
/// Gets or sets the item name.
|
||||
/// </summary>
|
||||
public string Name
|
||||
{
|
||||
get => _name ?? Id;
|
||||
set => _name = value;
|
||||
}
|
||||
public string Name { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -158,6 +161,11 @@ namespace Steeltoe.InitializrApi.Models
|
|||
/// </summary>
|
||||
public class GroupList : ItemList
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the default dependencies.
|
||||
/// </summary>
|
||||
public string Default { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the groups.
|
||||
/// </summary>
|
||||
|
|
|
@ -0,0 +1,138 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Text;
|
||||
|
||||
namespace Steeltoe.InitializrApi.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// A model of the project generation spec.
|
||||
/// </summary>
|
||||
public sealed class ProjectSpec
|
||||
{
|
||||
/* ----------------------------------------------------------------- *
|
||||
* fields *
|
||||
* ----------------------------------------------------------------- */
|
||||
|
||||
private string _archiveMimeType;
|
||||
|
||||
/* ----------------------------------------------------------------- *
|
||||
* properties *
|
||||
* ----------------------------------------------------------------- */
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the project name.
|
||||
/// </summary>
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the project description.
|
||||
/// </summary>
|
||||
public string Description { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the project namespace.
|
||||
/// </summary>
|
||||
public string Namespace { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Steeltoe version.
|
||||
/// </summary>
|
||||
public string SteeltoeVersion { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the DotNet framework ID.
|
||||
/// </summary>
|
||||
public string DotNetFramework { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the DotNet template ID.
|
||||
/// </summary>
|
||||
public string DotNetTemplate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the language ID.
|
||||
/// </summary>
|
||||
public string Language { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the project archive mime type.
|
||||
/// </summary>
|
||||
public string ArchiveMimeType
|
||||
{
|
||||
get => _archiveMimeType;
|
||||
set => _archiveMimeType = value is null ? null : (value.Contains('/') ? value : $"application/{value}");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the project dependencies.
|
||||
/// </summary>
|
||||
public string Dependencies { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Returns a user-friendly representation of the current object.
|
||||
/// </summary>
|
||||
/// <returns>Returns a user-friendly string that represents the current object.</returns>
|
||||
public override string ToString()
|
||||
{
|
||||
var buf = new StringBuilder();
|
||||
var delim = string.Empty;
|
||||
buf.Append('[');
|
||||
if (Name != null)
|
||||
{
|
||||
buf.Append(delim).Append("name=").Append(Name);
|
||||
delim = ",";
|
||||
}
|
||||
|
||||
if (Description != null)
|
||||
{
|
||||
buf.Append(delim).Append("description=").Append(Description);
|
||||
delim = ",";
|
||||
}
|
||||
|
||||
if (Namespace != null)
|
||||
{
|
||||
buf.Append(delim).Append("namespace=").Append(Namespace);
|
||||
delim = ",";
|
||||
}
|
||||
|
||||
if (SteeltoeVersion != null)
|
||||
{
|
||||
buf.Append(delim).Append("steeltoeVersion=").Append(SteeltoeVersion);
|
||||
delim = ",";
|
||||
}
|
||||
|
||||
if (DotNetFramework != null)
|
||||
{
|
||||
buf.Append(delim).Append("dotNetFramework=").Append(DotNetFramework);
|
||||
delim = ",";
|
||||
}
|
||||
|
||||
if (DotNetTemplate != null)
|
||||
{
|
||||
buf.Append(delim).Append("dotNetTemplate=").Append(DotNetTemplate);
|
||||
delim = ",";
|
||||
}
|
||||
|
||||
if (Language != null)
|
||||
{
|
||||
buf.Append(delim).Append("language=").Append(Language);
|
||||
delim = ",";
|
||||
}
|
||||
|
||||
if (ArchiveMimeType != null)
|
||||
{
|
||||
buf.Append(delim).Append("archiveMimeType=").Append(ArchiveMimeType);
|
||||
}
|
||||
|
||||
if (Dependencies != null)
|
||||
{
|
||||
buf.Append(delim).Append("dependencies=").Append(Dependencies);
|
||||
}
|
||||
|
||||
buf.Append(']');
|
||||
return buf.ToString();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
namespace Steeltoe.InitializrApi.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// A model of the specification used to generate a project.
|
||||
/// </summary>
|
||||
public sealed class ProjectSpecification
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the project name.
|
||||
/// </summary>
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the project description.
|
||||
/// </summary>
|
||||
public string Description { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Steeltoe version.
|
||||
/// </summary>
|
||||
public string SteeltoeVersion { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the DotNet target framework.
|
||||
/// </summary>
|
||||
public string DotnetTargetFrameworkId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the DotNet template ID.
|
||||
/// </summary>
|
||||
public string DotnetTemplateId { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the DotNet language.
|
||||
/// </summary>
|
||||
public string DotnetLanguageId { get; set; }
|
||||
}
|
||||
}
|
|
@ -1,39 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
|
||||
namespace Steeltoe.InitializrApi.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// A model of project template configuration metadata used by InitializrApi.
|
||||
/// </summary>
|
||||
public class ProjectTemplateConfiguration
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the project template URI.
|
||||
/// </summary>
|
||||
public Uri Uri { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the project template Steeltoe version range.
|
||||
/// </summary>
|
||||
public string SteeltoeVersionRange { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the project template DotNet version range.
|
||||
/// </summary>
|
||||
public string DotNetVersionRange { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the project template DotNet template type.
|
||||
/// </summary>
|
||||
public string Type { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the project template language.
|
||||
/// </summary>
|
||||
public string Language { get; set; }
|
||||
}
|
||||
}
|
|
@ -1,7 +1,11 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="YamlDotNet" Version="8.1.2" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Steeltoe.InitializrApi.Services;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Steeltoe.InitializrApi.Archivers
|
||||
{
|
||||
/// <summary>
|
||||
/// An in-memory <see cref="IArchiverRegistry"/> implementation.
|
||||
/// </summary>
|
||||
public class ArchiverRegistry : InitializrApiServiceBase, IArchiverRegistry
|
||||
{
|
||||
/* ----------------------------------------------------------------- *
|
||||
* fields *
|
||||
* ----------------------------------------------------------------- */
|
||||
|
||||
private readonly Dictionary<string, IArchiver> _archivers = new Dictionary<string, IArchiver>();
|
||||
|
||||
/* ----------------------------------------------------------------- *
|
||||
* constructors *
|
||||
* ----------------------------------------------------------------- */
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ArchiverRegistry"/> class.
|
||||
/// </summary>
|
||||
/// <param name="logger">Injected logger.</param>
|
||||
public ArchiverRegistry(ILogger<ArchiverRegistry> logger)
|
||||
: base(logger)
|
||||
{
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------- *
|
||||
* methods *
|
||||
* ----------------------------------------------------------------- */
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Initialize()
|
||||
{
|
||||
Logger.LogInformation("Initializing archiver registry.");
|
||||
|
||||
_archivers.Clear();
|
||||
Register(new ZipArchiver());
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Register(IArchiver archiver)
|
||||
{
|
||||
Logger.LogInformation(
|
||||
"Registering archive mime type: {{MimeType}} [{{Archiver}}]",
|
||||
archiver.GetMimeType(),
|
||||
archiver.GetType());
|
||||
_archivers.Add(archiver.GetMimeType(), archiver);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IArchiver Lookup(string mimeType)
|
||||
{
|
||||
_archivers.TryGetValue(mimeType, out var archiver);
|
||||
return archiver;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,100 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using Steeltoe.InitializrApi.Models;
|
||||
using Steeltoe.InitializrApi.Services;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
namespace Steeltoe.InitializrApi.Archivers
|
||||
{
|
||||
/// <summary>
|
||||
/// An <see cref="IArchiver"/> implementation using the ZIP archive file format.
|
||||
/// </summary>
|
||||
public class ZipArchiver : IArchiver
|
||||
{
|
||||
/* ----------------------------------------------------------------- *
|
||||
* constants *
|
||||
* ----------------------------------------------------------------- */
|
||||
|
||||
private const string MimeType = "application/zip";
|
||||
|
||||
private const string FileExtension = ".zip";
|
||||
|
||||
/* ----------------------------------------------------------------- *
|
||||
* Fix UNIX permissions in Zip archive extraction *
|
||||
* Owner *
|
||||
* Group *
|
||||
* Other *
|
||||
* r w r r *
|
||||
* ----------------------------------------------------------------- */
|
||||
private const int UnixPermissions = 0b_0000_0001_1010_0100_0000_0000_0000_0000;
|
||||
|
||||
/* ----------------------------------------------------------------- *
|
||||
* fields *
|
||||
* ----------------------------------------------------------------- */
|
||||
|
||||
private readonly CompressionLevel _compression;
|
||||
|
||||
/* ----------------------------------------------------------------- *
|
||||
* constructors *
|
||||
* ----------------------------------------------------------------- */
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ZipArchiver"/> class.
|
||||
/// </summary>
|
||||
/// <param name="compression">Compression level default <see cref="CompressionLevel.Fastest"/>.</param>
|
||||
public ZipArchiver(CompressionLevel compression = CompressionLevel.Fastest)
|
||||
{
|
||||
_compression = compression;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------- *
|
||||
* methods *
|
||||
* ----------------------------------------------------------------- */
|
||||
|
||||
/// <inheritdoc/>
|
||||
public byte[] ToBytes(IEnumerable<FileEntry> fileEntries)
|
||||
{
|
||||
var buffer = new MemoryStream();
|
||||
var archive = new ZipArchive(buffer, ZipArchiveMode.Create, true);
|
||||
foreach (var fileEntry in fileEntries)
|
||||
{
|
||||
var zipEntry = archive.CreateEntry(fileEntry.Path, _compression);
|
||||
if (fileEntry.Text == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||
{
|
||||
zipEntry.ExternalAttributes = UnixPermissions;
|
||||
}
|
||||
|
||||
using var textStream = new MemoryStream(Encoding.UTF8.GetBytes(fileEntry.Text));
|
||||
using var zipStream = zipEntry.Open();
|
||||
textStream.CopyTo(zipStream);
|
||||
}
|
||||
|
||||
archive.Dispose();
|
||||
buffer.Seek(0, SeekOrigin.Begin);
|
||||
return buffer.ToArray();
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string GetMimeType()
|
||||
{
|
||||
return MimeType;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public string GetFileExtension()
|
||||
{
|
||||
return FileExtension;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using Microsoft.Extensions.Options;
|
||||
using Steeltoe.InitializrApi.Models;
|
||||
using Steeltoe.InitializrApi.Services;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Steeltoe.InitializrApi.Configuration
|
||||
{
|
||||
/// <summary>
|
||||
/// An <see cref="IConfigurationRepository"/> using a <a href="https://cloud.spring.io/spring-cloud-config/reference/html/#_spring_cloud_config_server">Spring Cloud Config Server</a> backend.
|
||||
/// </summary>
|
||||
public class ConfigServerConfigurationRepository : IConfigurationRepository
|
||||
{
|
||||
private readonly InitializrApiConfiguration _configuration;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ConfigServerConfigurationRepository"/> class.
|
||||
/// </summary>
|
||||
/// <param name="configuration">Injected configuration from Config Server.</param>
|
||||
public ConfigServerConfigurationRepository(IOptions<InitializrApiConfiguration> configuration)
|
||||
{
|
||||
_configuration = configuration.Value;
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Task<InitializrApiConfiguration> GetConfiguration()
|
||||
{
|
||||
var result = new TaskCompletionSource<InitializrApiConfiguration>();
|
||||
result.SetResult(_configuration);
|
||||
return result.Task;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Steeltoe.InitializrApi.Models;
|
||||
using Steeltoe.InitializrApi.Services;
|
||||
|
||||
namespace Steeltoe.InitializrApi.Configuration
|
||||
{
|
||||
/// <summary>
|
||||
/// An <see cref="IInitializrConfigService"/> using a <a href="https://cloud.spring.io/spring-cloud-config/reference/html/#_spring_cloud_config_server">Spring Cloud Config Server</a> backend.
|
||||
/// </summary>
|
||||
public class InitializrConfigService : InitializrApiServiceBase, IInitializrConfigService
|
||||
{
|
||||
/* ----------------------------------------------------------------- *
|
||||
* fields *
|
||||
* ----------------------------------------------------------------- */
|
||||
|
||||
private readonly InitializrConfig _config;
|
||||
|
||||
/* ----------------------------------------------------------------- *
|
||||
* constructors *
|
||||
* ----------------------------------------------------------------- */
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="InitializrConfigService"/> class.
|
||||
/// </summary>
|
||||
/// <param name="configuration">Injected configuration from Config Server.</param>
|
||||
/// <param name="logger">Injected logger.</param>
|
||||
public InitializrConfigService(
|
||||
IOptions<InitializrConfig> configuration,
|
||||
ILogger<InitializrConfigService> logger)
|
||||
: base(logger)
|
||||
{
|
||||
_config = configuration.Value;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------- *
|
||||
* methods *
|
||||
* ----------------------------------------------------------------- */
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Initialize()
|
||||
{
|
||||
Logger.LogInformation("Initializing Initializr configuration.");
|
||||
if (_config.ProjectMetadata is null)
|
||||
{
|
||||
Logger.LogError("Project metadata missing.");
|
||||
}
|
||||
|
||||
if (_config.ProjectTemplates is null)
|
||||
{
|
||||
Logger.LogError("Project templates configuration missing.");
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public InitializrConfig GetInitializrConfig()
|
||||
{
|
||||
return _config;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -3,6 +3,7 @@
|
|||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Steeltoe.InitializrApi.Controllers
|
||||
{
|
||||
|
@ -11,8 +12,25 @@ namespace Steeltoe.InitializrApi.Controllers
|
|||
/// </summary>
|
||||
[ApiController]
|
||||
[Route("api/[controller]")]
|
||||
public class AboutController : ControllerBase
|
||||
public class AboutController : InitializrApiControllerBase
|
||||
{
|
||||
/* ----------------------------------------------------------------- *
|
||||
* constructors *
|
||||
* ----------------------------------------------------------------- */
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="AboutController"/> class.
|
||||
/// </summary>
|
||||
/// <param name="logger">Injected logger.</param>
|
||||
public AboutController(ILogger<AboutController> logger)
|
||||
: base(logger)
|
||||
{
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------- *
|
||||
* methods *
|
||||
* ----------------------------------------------------------------- */
|
||||
|
||||
/// <summary>
|
||||
/// Implements <c>GET</c>.
|
||||
/// </summary>
|
||||
|
|
|
@ -0,0 +1,78 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Steeltoe.InitializrApi.Models;
|
||||
using Steeltoe.InitializrApi.Services;
|
||||
|
||||
namespace Steeltoe.InitializrApi.Controllers
|
||||
{
|
||||
/// <summary>
|
||||
/// Server configuration endpoint.
|
||||
/// </summary>
|
||||
[ApiController]
|
||||
[Route("api/[controller]")]
|
||||
public class ConfigController : InitializrApiControllerBase
|
||||
{
|
||||
/* ----------------------------------------------------------------- *
|
||||
* fields *
|
||||
* ----------------------------------------------------------------- */
|
||||
|
||||
private readonly InitializrConfig _config;
|
||||
|
||||
/* ----------------------------------------------------------------- *
|
||||
* constructors *
|
||||
* ----------------------------------------------------------------- */
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ConfigController"/> class.
|
||||
/// </summary>
|
||||
/// <param name="configService">Injected configuration repository.</param>
|
||||
/// <param name="logger">Injected logger.</param>
|
||||
public ConfigController(
|
||||
IInitializrConfigService configService,
|
||||
ILogger<ConfigController> logger)
|
||||
: base(logger)
|
||||
{
|
||||
_config = configService.GetInitializrConfig();
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------- *
|
||||
* methods *
|
||||
* ----------------------------------------------------------------- */
|
||||
|
||||
/// <summary>
|
||||
/// Implements <c>GET</c> index.
|
||||
/// </summary>
|
||||
/// <returns>Returns a <c>GET</c> result which, if is <see cref="OkObjectResult"/>, contains the Initializr configuration.</returns>
|
||||
[HttpGet]
|
||||
public IActionResult GetInitializrConfiguration()
|
||||
{
|
||||
return Ok(_config);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Implements <c>GET projectMetadata</c>.
|
||||
/// </summary>
|
||||
/// <returns>Returns a <c>GET</c> result which, if is <see cref="OkObjectResult"/>, contains Initializr project metadata.</returns>
|
||||
[HttpGet]
|
||||
[Route("projectMetadata")]
|
||||
public IActionResult GetProjectMetadata()
|
||||
{
|
||||
return Ok(_config.ProjectMetadata);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Implements <c>GET projectTemplates</c>.
|
||||
/// </summary>
|
||||
/// <returns>Return a <c>GET</c> result which, if is <see cref="OkObjectResult"/>, contains InitializrApi project templates configuration.</returns>
|
||||
[HttpGet]
|
||||
[Route("projectTemplates")]
|
||||
public IActionResult GetProjectTemplatesConfig()
|
||||
{
|
||||
return Ok(_config.ProjectTemplates);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,64 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Steeltoe.InitializrApi.Services;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Steeltoe.InitializrApi.Controllers
|
||||
{
|
||||
/// <summary>
|
||||
/// Server configuration endpoint.
|
||||
/// </summary>
|
||||
[ApiController]
|
||||
[Route("api/[controller]")]
|
||||
public class ConfigurationController : ControllerBase
|
||||
{
|
||||
private readonly IConfigurationRepository _configurationRepository;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ConfigurationController"/> class.
|
||||
/// </summary>
|
||||
/// <param name="configurationRepository">Injected configuration repository.</param>
|
||||
public ConfigurationController(IConfigurationRepository configurationRepository)
|
||||
{
|
||||
_configurationRepository = configurationRepository;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Implements <c>GET</c> index.
|
||||
/// </summary>
|
||||
/// <returns>A task containing the <c>GET</c> result which, if is <see cref="OkObjectResult"/>, contains the server configuration.</returns>
|
||||
[HttpGet]
|
||||
public async Task<IActionResult> GetConfiguration()
|
||||
{
|
||||
var config = await _configurationRepository.GetConfiguration();
|
||||
return Ok(config);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Implements <c>GET metadata</c>.
|
||||
/// </summary>
|
||||
/// <returns>A task containing the <c>GET</c> result which, if is <see cref="OkObjectResult"/>, contains project metadata configuration.</returns>
|
||||
[HttpGet]
|
||||
[Route("metadata")]
|
||||
public async Task<IActionResult> GetMetadata()
|
||||
{
|
||||
var config = await _configurationRepository.GetConfiguration();
|
||||
return Ok(config.Metadata);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Implements <c>GET templates</c>.
|
||||
/// </summary>
|
||||
/// <returns>A task containing the <c>GET</c> result which, if is <see cref="OkObjectResult"/>, contains templates configuration.</returns>
|
||||
[HttpGet]
|
||||
[Route("templates")]
|
||||
public async Task<IActionResult> GetTemplates()
|
||||
{
|
||||
var config = await _configurationRepository.GetConfiguration();
|
||||
return Ok(config.Templates);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Steeltoe.InitializrApi.Controllers
|
||||
{
|
||||
/// <summary>
|
||||
/// Base class for InitializrApi controllers.
|
||||
/// </summary>
|
||||
public abstract class InitializrApiControllerBase : ControllerBase
|
||||
{
|
||||
/* ----------------------------------------------------------------- *
|
||||
* constructors *
|
||||
* ----------------------------------------------------------------- */
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="InitializrApiControllerBase"/> class.
|
||||
/// </summary>
|
||||
/// <param name="logger">Injected logger.</param>
|
||||
protected InitializrApiControllerBase(ILogger logger)
|
||||
{
|
||||
Logger = logger;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------- *
|
||||
* properties *
|
||||
* ----------------------------------------------------------------- */
|
||||
|
||||
/// <summary>
|
||||
/// Gets the logger.
|
||||
/// </summary>
|
||||
protected ILogger Logger { get; }
|
||||
}
|
||||
}
|
|
@ -2,14 +2,13 @@
|
|||
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Steeltoe.InitializrApi.Models;
|
||||
using Steeltoe.InitializrApi.Services;
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Net.Mime;
|
||||
using System.Threading.Tasks;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Steeltoe.InitializrApi.Controllers
|
||||
{
|
||||
|
@ -18,41 +17,117 @@ namespace Steeltoe.InitializrApi.Controllers
|
|||
/// </summary>
|
||||
[ApiController]
|
||||
[Route("api/[controller]")]
|
||||
public class ProjectController : ControllerBase
|
||||
public class ProjectController : InitializrApiControllerBase
|
||||
{
|
||||
/* ----------------------------------------------------------------- *
|
||||
* fields *
|
||||
* ----------------------------------------------------------------- */
|
||||
|
||||
private readonly InitializrConfig _config;
|
||||
|
||||
private readonly IProjectGenerator _projectGenerator;
|
||||
|
||||
private readonly ILogger<ProjectController> _logger;
|
||||
private readonly IArchiverRegistry _archiverRegistry;
|
||||
|
||||
/* ----------------------------------------------------------------- *
|
||||
* constructors *
|
||||
* ----------------------------------------------------------------- */
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ProjectController"/> class.
|
||||
/// </summary>
|
||||
/// <param name="configService">Injected Initializr configuration service.</param>
|
||||
/// <param name="projectGenerator">Injected project generator.</param>
|
||||
/// <param name="archiverRegistry">Injected archiver registry.</param>
|
||||
/// <param name="logger">Injected logger.</param>
|
||||
public ProjectController(IProjectGenerator projectGenerator, ILogger<ProjectController> logger)
|
||||
public ProjectController(
|
||||
IInitializrConfigService configService,
|
||||
IProjectGenerator projectGenerator,
|
||||
IArchiverRegistry archiverRegistry,
|
||||
ILogger<ProjectController> logger)
|
||||
: base(logger)
|
||||
{
|
||||
_config = configService.GetInitializrConfig();
|
||||
_projectGenerator = projectGenerator;
|
||||
_logger = logger;
|
||||
_archiverRegistry = archiverRegistry;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------- *
|
||||
* methods *
|
||||
* ----------------------------------------------------------------- */
|
||||
|
||||
/// <summary>
|
||||
/// Implements <c>GET</c>.
|
||||
/// Generated project is bundled in a ZIP archive.
|
||||
/// </summary>
|
||||
/// <returns>A task containing the <c>GET</c> result which, if is <see cref="FileContentResult"/>, contains a project bundle archive stream.</returns>
|
||||
[HttpGet]
|
||||
public async Task<ActionResult> Get([FromQuery] ProjectSpecification spec)
|
||||
public ActionResult GetProjectArchive([FromQuery] ProjectSpec spec)
|
||||
{
|
||||
_logger.LogDebug($"Project specification: {spec}");
|
||||
var stream = await _projectGenerator.GenerateProject(spec);
|
||||
byte[] bytes;
|
||||
await using (var buf = new MemoryStream())
|
||||
var defaults = _config.ProjectMetadata;
|
||||
var normalizedSpec = new ProjectSpec()
|
||||
{
|
||||
await stream.CopyToAsync(buf);
|
||||
bytes = buf.ToArray();
|
||||
Name = spec.Name ?? defaults?.Name?.Default,
|
||||
Description = spec.Description ?? defaults?.Description?.Default,
|
||||
Namespace = spec.Namespace ?? defaults?.Namespace?.Default,
|
||||
SteeltoeVersion = spec.SteeltoeVersion ?? defaults?.SteeltoeVersion?.Default,
|
||||
DotNetFramework = spec.DotNetFramework ?? defaults?.DotNetFramework?.Default,
|
||||
DotNetTemplate = spec.DotNetTemplate ?? defaults?.DotNetTemplate?.Default,
|
||||
Language = spec.Language ?? defaults?.Language?.Default,
|
||||
ArchiveMimeType = spec.ArchiveMimeType ?? defaults?.ArchiveMimeType?.Default,
|
||||
Dependencies = spec.Dependencies ?? defaults?.Dependencies?.Default,
|
||||
};
|
||||
if (normalizedSpec.ArchiveMimeType is null)
|
||||
{
|
||||
return StatusCode(
|
||||
StatusCodes.Status500InternalServerError,
|
||||
"Default archive mime type not configured.");
|
||||
}
|
||||
|
||||
return File(bytes, MediaTypeNames.Application.Zip, $"{spec.Name}.zip");
|
||||
var archiver = _archiverRegistry.Lookup(normalizedSpec.ArchiveMimeType);
|
||||
if (archiver is null)
|
||||
{
|
||||
return NotFound($"Archive mime type '{normalizedSpec.ArchiveMimeType}' not found.");
|
||||
}
|
||||
|
||||
if (normalizedSpec.Dependencies != null && _config.ProjectMetadata?.Dependencies?.Values != null)
|
||||
{
|
||||
var caseSensitiveDeps = new List<string>();
|
||||
foreach (var group in _config.ProjectMetadata.Dependencies.Values)
|
||||
{
|
||||
foreach (var dep in group.Values)
|
||||
{
|
||||
caseSensitiveDeps.Add(dep.Id);
|
||||
}
|
||||
}
|
||||
|
||||
var deps = normalizedSpec.Dependencies.Split(',');
|
||||
for (int i = 0; i < deps.Length; ++i)
|
||||
{
|
||||
foreach (var caseSensitiveDep in caseSensitiveDeps)
|
||||
{
|
||||
if (caseSensitiveDep.Equals(deps[i], StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
deps[i] = caseSensitiveDep;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
normalizedSpec.Dependencies = string.Join(',', deps);
|
||||
}
|
||||
|
||||
Logger.LogDebug("Project specification: {ProjectSpec}", normalizedSpec);
|
||||
var project = _projectGenerator.GenerateProject(normalizedSpec);
|
||||
if (project is null)
|
||||
{
|
||||
return NotFound($"No such project for spec: {normalizedSpec}");
|
||||
}
|
||||
|
||||
var archiveBytes = archiver.ToBytes(project.FileEntries);
|
||||
return File(
|
||||
archiveBytes,
|
||||
normalizedSpec.ArchiveMimeType,
|
||||
$"{normalizedSpec.Name}{archiver.GetFileExtension()}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
namespace Steeltoe.InitializrApi.Expressions
|
||||
{
|
||||
internal abstract class BooleanOperatorToken : OperatorToken
|
||||
{
|
||||
}
|
||||
}
|
|
@ -0,0 +1,115 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Steeltoe.InitializrApi.Expressions
|
||||
{
|
||||
/// <summary>
|
||||
/// Parser for expressions.
|
||||
/// </summary>
|
||||
/// BNF:
|
||||
/// expression := operand | operand operator operand
|
||||
/// operator := booleanOperator
|
||||
/// booleanOperator := orOperator
|
||||
/// orOperator := "||"
|
||||
/// operand := parameter
|
||||
/// parameter := alpha | alpha alphanumeric
|
||||
/// alpha := "a-Z"
|
||||
/// digit := "0-9"
|
||||
/// alphanumeric := alpha | digit
|
||||
public class Expression<T>
|
||||
{
|
||||
private readonly IEnumerator<Token> _tokens;
|
||||
|
||||
private readonly Type _type;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Expression{T}"/> class.
|
||||
/// </summary>
|
||||
/// <param name="expression">The expression in string form.</param>
|
||||
public Expression(string expression)
|
||||
{
|
||||
_type = typeof(T);
|
||||
_tokens = new Tokenizer().Scan(expression).GetEnumerator();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Evaluates the expression.
|
||||
/// </summary>
|
||||
/// <param name="parameters"> Expression parameters.</param>
|
||||
/// <returns>The evaluation.</returns>
|
||||
public T Evaluate(Dictionary<string, object> parameters)
|
||||
{
|
||||
if (_type == typeof(bool))
|
||||
{
|
||||
return (T)(object)EvaluateBooleanExpression(parameters);
|
||||
}
|
||||
|
||||
return default(T);
|
||||
}
|
||||
|
||||
private bool EvaluateBooleanExpression(Dictionary<string, object> parameters)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
while (_tokens.MoveNext())
|
||||
{
|
||||
switch (_tokens.Current)
|
||||
{
|
||||
case ParameterToken parameter:
|
||||
result = GetBooleanValue(parameter.Name, parameters);
|
||||
break;
|
||||
default:
|
||||
throw new ExpressionException($"Expected a parameter: {_tokens.Current}");
|
||||
}
|
||||
|
||||
if (!_tokens.MoveNext())
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
do
|
||||
{
|
||||
if (!(_tokens.Current is OrOperatorToken))
|
||||
{
|
||||
throw new ExpressionException($"Expected an or operator: {_tokens.Current}");
|
||||
}
|
||||
|
||||
if (!_tokens.MoveNext())
|
||||
{
|
||||
throw new ExpressionException($"Expected a parameter.");
|
||||
}
|
||||
|
||||
switch (_tokens.Current)
|
||||
{
|
||||
case ParameterToken parameter:
|
||||
result = result || GetBooleanValue(parameter.Name, parameters);
|
||||
break;
|
||||
default:
|
||||
throw new ExpressionException($"Expected a parameter: {_tokens.Current}");
|
||||
}
|
||||
}
|
||||
while (_tokens.MoveNext());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private bool GetBooleanValue(string name, Dictionary<string, object> parameters)
|
||||
{
|
||||
if (parameters.ContainsKey(name))
|
||||
{
|
||||
var value = parameters[name];
|
||||
if (value is bool)
|
||||
{
|
||||
return (bool)value;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
|
||||
namespace Steeltoe.InitializrApi.Expressions
|
||||
{
|
||||
/// <summary>
|
||||
/// An exception representing an error in an expression.
|
||||
/// </summary>
|
||||
public class ExpressionException : ArgumentException
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ExpressionException"/> class.
|
||||
/// </summary>
|
||||
/// <param name="message">The exception message.</param>
|
||||
public ExpressionException(string message)
|
||||
: base(message)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
namespace Steeltoe.InitializrApi.Expressions
|
||||
{
|
||||
internal abstract class OperandToken : Token
|
||||
{
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
namespace Steeltoe.InitializrApi.Expressions
|
||||
{
|
||||
internal abstract class OperatorToken : Token
|
||||
{
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
namespace Steeltoe.InitializrApi.Expressions
|
||||
{
|
||||
internal class OrOperatorToken : BooleanOperatorToken
|
||||
{
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
namespace Steeltoe.InitializrApi.Expressions
|
||||
{
|
||||
internal class ParameterToken : OperandToken
|
||||
{
|
||||
internal ParameterToken(string name)
|
||||
{
|
||||
Name = name;
|
||||
}
|
||||
|
||||
internal string Name { get; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
namespace Steeltoe.InitializrApi.Expressions
|
||||
{
|
||||
internal abstract class Token
|
||||
{
|
||||
}
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
|
||||
namespace Steeltoe.InitializrApi.Expressions
|
||||
{
|
||||
internal class Tokenizer
|
||||
{
|
||||
private const int EndOfString = -1;
|
||||
|
||||
internal IEnumerable<Token> Scan(string expression)
|
||||
{
|
||||
var reader = new StringReader(expression);
|
||||
var tokens = new List<Token>();
|
||||
while (reader.Peek() != EndOfString)
|
||||
{
|
||||
var ch = (char)reader.Peek();
|
||||
if (char.IsWhiteSpace(ch))
|
||||
{
|
||||
reader.Read();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (char.IsLetter(ch))
|
||||
{
|
||||
tokens.Add(ParseParameterToken(reader));
|
||||
}
|
||||
else if (ch.Equals('|'))
|
||||
{
|
||||
tokens.Add(ParseOrOperatorToken(reader));
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ExpressionException($"unexpected character: '{ch}'");
|
||||
}
|
||||
}
|
||||
|
||||
return tokens;
|
||||
}
|
||||
|
||||
private ParameterToken ParseParameterToken(StringReader reader)
|
||||
{
|
||||
var ch = (char)reader.Peek();
|
||||
if (!char.IsLetter(ch))
|
||||
{
|
||||
throw new ExpressionException($"expected a letter: '{ch}'");
|
||||
}
|
||||
|
||||
var buf = new StringBuilder();
|
||||
while (char.IsLetterOrDigit((char)reader.Peek()))
|
||||
{
|
||||
ch = (char)reader.Read();
|
||||
buf.Append(ch);
|
||||
}
|
||||
|
||||
return new ParameterToken(buf.ToString());
|
||||
}
|
||||
|
||||
private OrOperatorToken ParseOrOperatorToken(StringReader reader)
|
||||
{
|
||||
if (!((char)reader.Read()).Equals('|'))
|
||||
{
|
||||
throw new ExpressionException("expected character: '|'");
|
||||
}
|
||||
|
||||
if (!((char)reader.Read()).Equals('|'))
|
||||
{
|
||||
throw new ExpressionException("expected character: '|'");
|
||||
}
|
||||
|
||||
return new OrOperatorToken();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,24 +2,116 @@
|
|||
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Steeltoe.InitializrApi.Expressions;
|
||||
using Steeltoe.InitializrApi.Models;
|
||||
using Steeltoe.InitializrApi.Services;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
using Stubble.Core;
|
||||
using Stubble.Core.Builders;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Steeltoe.InitializrApi.Generators
|
||||
{
|
||||
/// <summary>
|
||||
/// An <see cref="IProjectGenerator"/> implementation using <a gref="https://github.com/StubbleOrg/Stubble">Stubble</a>, a Mustache template engine implemented in C#.
|
||||
/// </summary>
|
||||
public class StubbleProjectGenerator : IProjectGenerator
|
||||
public class StubbleProjectGenerator : InitializrApiServiceBase, IProjectGenerator
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
public Task<Stream> GenerateProject(ProjectSpecification specification)
|
||||
/* ----------------------------------------------------------------- *
|
||||
* fields *
|
||||
* ----------------------------------------------------------------- */
|
||||
|
||||
private readonly IProjectTemplateRegistry _projectTemplateRegistry;
|
||||
|
||||
private readonly StubbleVisitorRenderer _renderer;
|
||||
|
||||
/* ----------------------------------------------------------------- *
|
||||
* constructors *
|
||||
* ----------------------------------------------------------------- */
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="StubbleProjectGenerator"/> class.
|
||||
/// </summary>
|
||||
/// <param name="projectTemplateRegistry">Injected template registry.</param>
|
||||
/// <param name="logger">Injected logger.</param>
|
||||
public StubbleProjectGenerator(
|
||||
IProjectTemplateRegistry projectTemplateRegistry,
|
||||
ILogger<StubbleProjectGenerator> logger)
|
||||
: base(logger)
|
||||
{
|
||||
var result = new TaskCompletionSource<Stream>();
|
||||
result.SetResult(new MemoryStream());
|
||||
return result.Task;
|
||||
_projectTemplateRegistry = projectTemplateRegistry;
|
||||
_renderer = new StubbleBuilder()
|
||||
.Configure(settings => { settings.SetIgnoreCaseOnKeyLookup(true); })
|
||||
.Build();
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------- *
|
||||
* methods *
|
||||
* ----------------------------------------------------------------- */
|
||||
|
||||
/// <inheritdoc/>
|
||||
public Project GenerateProject(ProjectSpec spec)
|
||||
{
|
||||
var template = _projectTemplateRegistry.Lookup(spec);
|
||||
if (template is null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var parameters = new Dictionary<string, object>
|
||||
{
|
||||
["Name"] = spec.Name,
|
||||
["Description"] = spec.Description,
|
||||
["Namespace"] = spec.Namespace,
|
||||
["SteeltoeVersion"] = spec.SteeltoeVersion,
|
||||
["DotNetFramework"] = spec.DotNetFramework,
|
||||
["DotNetTemplate"] = spec.DotNetTemplate,
|
||||
["Language"] = spec.Language,
|
||||
};
|
||||
if (spec.Dependencies != null)
|
||||
{
|
||||
foreach (var dependency in spec.Dependencies?.Split(','))
|
||||
{
|
||||
parameters[dependency] = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (template.Parameters != null)
|
||||
{
|
||||
foreach (var templateParameter in template.Parameters)
|
||||
{
|
||||
parameters[templateParameter.Name] =
|
||||
new Expression<bool>(templateParameter.Expression).Evaluate(parameters);
|
||||
}
|
||||
}
|
||||
|
||||
var project = new Project();
|
||||
foreach (var fileEntry in template.Manifest)
|
||||
{
|
||||
if (fileEntry.Dependencies != null)
|
||||
{
|
||||
var dependencySatisfied = false;
|
||||
foreach (var fileEntryDependency in fileEntry.Dependencies.Split(','))
|
||||
{
|
||||
if (parameters.ContainsKey(fileEntryDependency))
|
||||
{
|
||||
dependencySatisfied = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!dependencySatisfied)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
var path = fileEntry.Rename is null ? fileEntry.Path : _renderer.Render(fileEntry.Rename, parameters);
|
||||
var text = fileEntry.Text is null ? null : _renderer.Render(fileEntry.Text, parameters);
|
||||
project.FileEntries.Add(new FileEntry { Path = path, Text = text });
|
||||
}
|
||||
|
||||
return project;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,8 +7,12 @@ namespace Steeltoe.InitializrApi.Models
|
|||
/// <summary>
|
||||
/// Application information, such as version.
|
||||
/// </summary>
|
||||
public class About
|
||||
public sealed class About
|
||||
{
|
||||
/* ----------------------------------------------------------------- *
|
||||
* properties *
|
||||
* ----------------------------------------------------------------- */
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the application name.
|
||||
/// </summary>
|
|
@ -0,0 +1,38 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
namespace Steeltoe.InitializrApi.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// A model a file entry or a directory entry.
|
||||
/// A file entry must have a path that does not end in '/' and text that is not null.
|
||||
/// A directory entry must have a path that ends in '/' and text that is null.
|
||||
/// </summary>
|
||||
public sealed class FileEntry
|
||||
{
|
||||
/* ----------------------------------------------------------------- *
|
||||
* properties *
|
||||
* ----------------------------------------------------------------- */
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the file path.
|
||||
/// </summary>
|
||||
public string Path { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the file text.
|
||||
/// </summary>
|
||||
public string Text { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the name to be renamed.
|
||||
/// </summary>
|
||||
public string Rename { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the associated dependencies.
|
||||
/// </summary>
|
||||
public string Dependencies { get; set; }
|
||||
}
|
||||
}
|
|
@ -7,16 +7,20 @@ namespace Steeltoe.InitializrApi.Models
|
|||
/// <summary>
|
||||
/// A model of an InitializrApi server configuration.
|
||||
/// </summary>
|
||||
public sealed class InitializrApiConfiguration
|
||||
public sealed class InitializrConfig
|
||||
{
|
||||
/* ----------------------------------------------------------------- *
|
||||
* properties *
|
||||
* ----------------------------------------------------------------- */
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the project metadata.
|
||||
/// </summary>
|
||||
public ProjectMetadata Metadata { get; set; }
|
||||
public ProjectMetadata ProjectMetadata { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the project template configurations.
|
||||
/// Gets or sets the project templates configuration.
|
||||
/// </summary>
|
||||
public ProjectTemplateConfiguration[] Templates { get; set; }
|
||||
public ProjectTemplateConfiguration[] ProjectTemplates { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Steeltoe.InitializrApi.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// A model of a project.
|
||||
/// </summary>
|
||||
public sealed class Project
|
||||
{
|
||||
/* ----------------------------------------------------------------- *
|
||||
* properties *
|
||||
* ----------------------------------------------------------------- */
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the spec used to create the project.
|
||||
/// </summary>
|
||||
public ProjectSpec Spec { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the file entries.
|
||||
/// </summary>
|
||||
public List<FileEntry> FileEntries { get; set; } = new List<FileEntry>();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Text;
|
||||
|
||||
namespace Steeltoe.InitializrApi.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// A model of project spec constraints.
|
||||
/// </summary>
|
||||
public sealed class ProjectSpecConstraints
|
||||
{
|
||||
/* ----------------------------------------------------------------- *
|
||||
* properties *
|
||||
* ----------------------------------------------------------------- */
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the Steeltoe version range.
|
||||
/// </summary>
|
||||
public string SteeltoeVersionRange { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the DotNet framework range.
|
||||
/// </summary>
|
||||
public string DotNetFrameworkRange { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the DotNet template.
|
||||
/// </summary>
|
||||
public string DotNetTemplate { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the language.
|
||||
/// </summary>
|
||||
public string Language { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Returns a user-friendly representation of the current object.
|
||||
/// </summary>
|
||||
/// <returns>Returns a user-friendly string that represents the current object.</returns>
|
||||
public override string ToString()
|
||||
{
|
||||
var buf = new StringBuilder();
|
||||
buf.Append('[');
|
||||
buf.Append("steeltoeVersionRange=");
|
||||
buf.Append(SteeltoeVersionRange);
|
||||
buf.Append(",dotNetFrameworkRange=");
|
||||
buf.Append(DotNetFrameworkRange);
|
||||
buf.Append(",dotNetTemplate=");
|
||||
buf.Append(DotNetTemplate);
|
||||
buf.Append(",language=");
|
||||
buf.Append(Language);
|
||||
buf.Append(']');
|
||||
return buf.ToString();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
namespace Steeltoe.InitializrApi.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// A model of a project template manifest an an IZR template bundle.
|
||||
/// </summary>
|
||||
public sealed class ProjectTemplate
|
||||
{
|
||||
/* ----------------------------------------------------------------- *
|
||||
* properties *
|
||||
* ----------------------------------------------------------------- */
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the description.
|
||||
/// </summary>
|
||||
public string Description { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the constraints.
|
||||
/// </summary>
|
||||
public ProjectSpecConstraints Constraints { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the files.
|
||||
/// </summary>
|
||||
public FileEntry[] Manifest { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the parameter expressions.
|
||||
/// </summary>
|
||||
public ParameterExpression[] Parameters { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// A model of a parameter expression.
|
||||
/// </summary>
|
||||
public class ParameterExpression
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the parameter name.
|
||||
/// </summary>
|
||||
public string Name { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the parameter expression.
|
||||
/// </summary>
|
||||
public string Expression { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
|
||||
namespace Steeltoe.InitializrApi.Models
|
||||
{
|
||||
/// <summary>
|
||||
/// A model of project template configuration.
|
||||
/// </summary>
|
||||
public sealed class ProjectTemplateConfiguration
|
||||
{
|
||||
/* ----------------------------------------------------------------- *
|
||||
* properties *
|
||||
* ----------------------------------------------------------------- */
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the project template URI.
|
||||
/// </summary>
|
||||
public Uri Uri { get; set; }
|
||||
}
|
||||
}
|
|
@ -3,9 +3,11 @@
|
|||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Steeltoe.Extensions.Configuration.ConfigServer;
|
||||
using Steeltoe.InitializrApi.Models;
|
||||
using Steeltoe.InitializrApi.Services;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Reflection;
|
||||
|
||||
|
@ -45,10 +47,13 @@ namespace Steeltoe.InitializrApi
|
|||
/// <summary>
|
||||
/// Program entrypoint.
|
||||
/// </summary>
|
||||
public static int Main(string[] args)
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
CreateHostBuilder(args).Build().Run();
|
||||
return 0;
|
||||
var host = CreateHostBuilder(args).Build();
|
||||
host.Services.GetRequiredService<IInitializrConfigService>().Initialize();
|
||||
host.Services.GetRequiredService<IProjectTemplateRegistry>().Initialize();
|
||||
host.Services.GetRequiredService<IArchiverRegistry>().Initialize();
|
||||
host.Run();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
"Development": {
|
||||
"commandName": "Project",
|
||||
"launchBrowser": false,
|
||||
"applicationUrl": "http://localhost:19200",
|
||||
"applicationUrl": "http://0.0.0.0:19200",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
|
@ -28,7 +28,7 @@
|
|||
"Staging": {
|
||||
"commandName": "Project",
|
||||
"launchBrowser": false,
|
||||
"applicationUrl": "https://localhost:19201;http://localhost:19200",
|
||||
"applicationUrl": "https://0.0.0.0:19201;http://0.0.0.0:19200",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Staging"
|
||||
}
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using Steeltoe.InitializrApi.Models;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Steeltoe.InitializrApi.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Contract for archiver implementations.
|
||||
/// </summary>
|
||||
public interface IArchiver
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns the archive as a byte array.
|
||||
/// </summary>
|
||||
/// <param name="fileEntries">File entries to be archived.</param>
|
||||
/// <returns>A new stream containing the archive.</returns>
|
||||
byte[] ToBytes(IEnumerable<FileEntry> fileEntries);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the MIME type for the archive format.
|
||||
/// </summary>
|
||||
/// <returns>The MIME type.</returns>
|
||||
string GetMimeType();
|
||||
|
||||
/// <summary>
|
||||
/// Gets the file extension for the archive.
|
||||
/// </summary>
|
||||
/// <returns>The file extension.</returns>
|
||||
string GetFileExtension();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
namespace Steeltoe.InitializrApi.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Contract for a archiver registry implementations.
|
||||
/// </summary>
|
||||
public interface IArchiverRegistry : IRegistry<IArchiver, string>
|
||||
{
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
namespace Steeltoe.InitializrApi.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Contract for services that can be initialized and reinitialized.
|
||||
/// </summary>
|
||||
public interface IInitializeable
|
||||
{
|
||||
/// <summary>
|
||||
/// Perform initialization.
|
||||
/// Called when started or reconfigured.
|
||||
/// </summary>
|
||||
void Initialize();
|
||||
}
|
||||
}
|
|
@ -3,19 +3,18 @@
|
|||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using Steeltoe.InitializrApi.Models;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Steeltoe.InitializrApi.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Contract for project configuration repository implementations.
|
||||
/// Contract for Initializr configuration service implementations.
|
||||
/// </summary>
|
||||
public interface IConfigurationRepository
|
||||
public interface IInitializrConfigService : IInitializeable
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the project generation configuration.
|
||||
/// Gets the Initializr configuration.
|
||||
/// </summary>
|
||||
/// <returns>A task containing server configuration.</returns>
|
||||
public Task<InitializrApiConfiguration> GetConfiguration();
|
||||
/// <returns>Returns an Initializr configuration.</returns>
|
||||
public InitializrConfig GetInitializrConfig();
|
||||
}
|
||||
}
|
|
@ -3,8 +3,6 @@
|
|||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using Steeltoe.InitializrApi.Models;
|
||||
using System.IO;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Steeltoe.InitializrApi.Services
|
||||
{
|
||||
|
@ -14,10 +12,10 @@ namespace Steeltoe.InitializrApi.Services
|
|||
public interface IProjectGenerator
|
||||
{
|
||||
/// <summary>
|
||||
/// Generates a project bundle as a ZIP archive byte stream.
|
||||
/// Generates a project based on the spec.
|
||||
/// </summary>
|
||||
/// <param name="specification">Project specification.</param>
|
||||
/// <returns>A task containing generated project bundle.</returns>
|
||||
public Task<Stream> GenerateProject(ProjectSpecification specification);
|
||||
/// <param name="spec">Project specification.</param>
|
||||
/// <returns>The generated project, or null if not able to generate project per spec.</returns>
|
||||
Project GenerateProject(ProjectSpec spec);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using Steeltoe.InitializrApi.Models;
|
||||
|
||||
namespace Steeltoe.InitializrApi.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Contract for project template registry implementations.
|
||||
/// </summary>
|
||||
public interface IProjectTemplateRegistry : IRegistry<ProjectTemplate, ProjectSpec>
|
||||
{
|
||||
}
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
namespace Steeltoe.InitializrApi.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Contract for registries.
|
||||
/// </summary>
|
||||
/// <typeparam name="TValue">The value to be registered.</typeparam>
|
||||
/// <typeparam name="TLookup">Key used to lookup a value.</typeparam>
|
||||
public interface IRegistry<TValue, TLookup> : IInitializeable
|
||||
{
|
||||
/// <summary>
|
||||
/// Registers the value.
|
||||
/// </summary>
|
||||
/// <param name="value">The value to register.</param>
|
||||
void Register(TValue value);
|
||||
|
||||
/// <summary>
|
||||
/// Look for a value that satisfies the key.
|
||||
/// </summary>
|
||||
/// <param name="lookup">The lookup key of the value to get.</param>
|
||||
/// <returns>A value associated with the lookup key, or <c>null</c> if no value found.</returns>
|
||||
TValue Lookup(TLookup lookup);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Steeltoe.InitializrApi.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Base class for InitializrApi services.
|
||||
/// </summary>
|
||||
public abstract class InitializrApiServiceBase
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="InitializrApiServiceBase"/> class.
|
||||
/// </summary>
|
||||
/// <param name="logger">Injected logger.</param>
|
||||
protected InitializrApiServiceBase(ILogger logger)
|
||||
{
|
||||
Logger = logger;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the logger.
|
||||
/// </summary>
|
||||
protected ILogger Logger { get; }
|
||||
}
|
||||
}
|
|
@ -9,12 +9,13 @@ using Microsoft.Extensions.DependencyInjection;
|
|||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Steeltoe.Extensions.Configuration.ConfigServer;
|
||||
using Steeltoe.InitializrApi.Archivers;
|
||||
using Steeltoe.InitializrApi.Configuration;
|
||||
using Steeltoe.InitializrApi.Generators;
|
||||
using Steeltoe.InitializrApi.Models;
|
||||
using Steeltoe.InitializrApi.Services;
|
||||
using Steeltoe.InitializrApi.Templates;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Transactions;
|
||||
|
||||
namespace Steeltoe.InitializrApi
|
||||
{
|
||||
|
@ -39,17 +40,23 @@ namespace Steeltoe.InitializrApi
|
|||
public IConfiguration Configuration { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Called by the runtime. Adds <see cref="IConfigurationRepository"/> and <see cref="IProjectGenerator"/> services.
|
||||
/// Called by the runtime. Adds <see cref="IInitializrConfigService"/> and <see cref="IProjectGenerator"/> services.
|
||||
/// </summary>
|
||||
/// <param name="services">Injected services.</param>
|
||||
public void ConfigureServices(IServiceCollection services)
|
||||
{
|
||||
services.AddOptions();
|
||||
services.ConfigureConfigServerClientOptions(Configuration);
|
||||
services.Configure<InitializrApiConfiguration>(Configuration);
|
||||
services.AddSingleton<IConfigurationRepository, ConfigServerConfigurationRepository>();
|
||||
services.AddSingleton<IProjectGenerator, StubbleProjectGenerator>();
|
||||
services.AddControllers().AddJsonOptions(options => options.JsonSerializerOptions.IgnoreNullValues = true);
|
||||
services.Configure<InitializrConfig>(Configuration);
|
||||
services.AddSingleton<IInitializrConfigService, InitializrConfigService>();
|
||||
services.AddSingleton<IProjectTemplateRegistry, ProjectTemplateRegistry>();
|
||||
services.AddSingleton<IArchiverRegistry, ArchiverRegistry>();
|
||||
services.AddTransient<IProjectGenerator, StubbleProjectGenerator>();
|
||||
services.AddControllers().AddJsonOptions(options =>
|
||||
{
|
||||
options.JsonSerializerOptions.IgnoreNullValues = true;
|
||||
options.JsonSerializerOptions.PropertyNameCaseInsensitive = true;
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -61,7 +68,7 @@ namespace Steeltoe.InitializrApi
|
|||
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, ILogger<Startup> logger)
|
||||
{
|
||||
var about = Program.About;
|
||||
logger.LogInformation($"{about.Name}, version {about.Version} [{about.Commit}]");
|
||||
logger.LogInformation("{Program}, version {Version} [{Commit}]", about.Name, about.Version, about.Commit);
|
||||
|
||||
if (env.IsDevelopment())
|
||||
{
|
||||
|
|
|
@ -1,20 +1,22 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Steeltoe.Extensions.Configuration.ConfigServerCore" Version="3.0.0-m2" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Steeltoe.Extensions.Configuration.ConfigServerCore" Version="3.0.0-m2" />
|
||||
<PackageReference Include="Stubble.Core" Version="1.9.3" />
|
||||
<PackageReference Include="YamlDotNet" Version="8.1.2" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\InitializrApi.Models\Steeltoe.InitializrApi.Models.csproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\InitializrApi.Models\Steeltoe.InitializrApi.Models.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="..\DeterministicBuild.targets">
|
||||
<Link>DeterministicBuild.targets</Link>
|
||||
</Content>
|
||||
<Content Include="..\Directory.Build.props">
|
||||
<Link>Directory.Build.props</Link>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Content Include="..\DeterministicBuild.targets">
|
||||
<Link>DeterministicBuild.targets</Link>
|
||||
</Content>
|
||||
<Content Include="..\Directory.Build.props">
|
||||
<Link>Directory.Build.props</Link>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
|
|
@ -0,0 +1,214 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Steeltoe.InitializrApi.Models;
|
||||
using Steeltoe.InitializrApi.Services;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Net;
|
||||
using YamlDotNet.Core;
|
||||
using YamlDotNet.Serialization;
|
||||
using YamlDotNet.Serialization.NamingConventions;
|
||||
|
||||
namespace Steeltoe.InitializrApi.Templates
|
||||
{
|
||||
/// <summary>
|
||||
/// A simple <see cref="IProjectTemplateRegistry"/> implementation.
|
||||
/// </summary>
|
||||
public class ProjectTemplateRegistry : InitializrApiServiceBase, IProjectTemplateRegistry
|
||||
{
|
||||
/* ----------------------------------------------------------------- *
|
||||
* constants *
|
||||
* ----------------------------------------------------------------- */
|
||||
|
||||
private const string Metadata = ".IZR/metadata.yaml";
|
||||
|
||||
/* ----------------------------------------------------------------- *
|
||||
* fields *
|
||||
* ----------------------------------------------------------------- */
|
||||
|
||||
private readonly IInitializrConfigService _configService;
|
||||
|
||||
private readonly List<(ProjectSpecConstraints Constraints, ProjectTemplate Template)> _templates =
|
||||
new List<(ProjectSpecConstraints Constraints, ProjectTemplate Template)>();
|
||||
|
||||
/* ----------------------------------------------------------------- *
|
||||
* constructors *
|
||||
* ----------------------------------------------------------------- */
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ProjectTemplateRegistry"/> class.
|
||||
/// </summary>
|
||||
/// <param name="configService">Injected Initializr configuration service.</param>
|
||||
/// <param name="logger">Injected logger.</param>
|
||||
public ProjectTemplateRegistry(
|
||||
IInitializrConfigService configService,
|
||||
ILogger<ProjectTemplateRegistry> logger)
|
||||
: base(logger)
|
||||
{
|
||||
_configService = configService;
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------- *
|
||||
* methods *
|
||||
* ----------------------------------------------------------------- */
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Initialize()
|
||||
{
|
||||
Logger.LogInformation("Initializing project template registry.");
|
||||
_templates.Clear();
|
||||
var config = _configService.GetInitializrConfig();
|
||||
if (config.ProjectTemplates is null)
|
||||
{
|
||||
Logger.LogError("Templates not configured.");
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var templateConfig in config.ProjectTemplates)
|
||||
{
|
||||
Register(templateConfig.Uri);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public void Register(ProjectTemplate projectTemplate)
|
||||
{
|
||||
Logger.LogInformation(
|
||||
$"Registering project template: {projectTemplate.Constraints} ({projectTemplate.Description})");
|
||||
_templates.Add((projectTemplate.Constraints, projectTemplate));
|
||||
}
|
||||
|
||||
/// <inheritdoc/>
|
||||
public ProjectTemplate Lookup(ProjectSpec spec)
|
||||
{
|
||||
foreach (var template in _templates)
|
||||
{
|
||||
var constraints = template.Constraints;
|
||||
if ((constraints.SteeltoeVersionRange is null
|
||||
|| constraints.SteeltoeVersionRange.Equals(spec.SteeltoeVersion))
|
||||
&& (constraints.DotNetFrameworkRange is null
|
||||
|| constraints.DotNetFrameworkRange.Equals(spec.DotNetFramework))
|
||||
&& (constraints.DotNetTemplate is null
|
||||
|| constraints.DotNetTemplate.Equals(spec.DotNetTemplate))
|
||||
&& (constraints.Language is null
|
||||
|| constraints.Language.Equals(spec.Language)))
|
||||
{
|
||||
return template.Template;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private void Register(Uri uri)
|
||||
{
|
||||
Logger.LogInformation("Fetching project template: {Uri}", uri);
|
||||
try
|
||||
{
|
||||
var request = WebRequest.Create(uri);
|
||||
using var response = request.GetResponse();
|
||||
using var stream = response.GetResponseStream();
|
||||
if (stream is null)
|
||||
{
|
||||
Logger.LogError("URI returned null stream: {TemplateUri}", uri);
|
||||
return;
|
||||
}
|
||||
|
||||
using var archive = new ZipArchive(stream);
|
||||
ProjectTemplate projectTemplate;
|
||||
try
|
||||
{
|
||||
projectTemplate = ParseZipEntry<ProjectTemplate>(archive.GetEntry(Metadata));
|
||||
if (projectTemplate is null)
|
||||
{
|
||||
Logger.LogError($"Project template metadata missing ('{Metadata}'): {{TemplateUri}}", uri);
|
||||
return;
|
||||
}
|
||||
|
||||
if (projectTemplate.Constraints is null)
|
||||
{
|
||||
Logger.LogError("Project template constraints missing: {TemplateUri}", uri);
|
||||
return;
|
||||
}
|
||||
|
||||
if (projectTemplate.Manifest is null)
|
||||
{
|
||||
Logger.LogError("Project template manifest missing: {TemplateUri}", uri);
|
||||
return;
|
||||
}
|
||||
}
|
||||
catch (YamlException e)
|
||||
{
|
||||
Logger.LogError(e, "Project template metadata malformed ('{Path}'): {TemplateUri}", Metadata, uri);
|
||||
return;
|
||||
}
|
||||
|
||||
foreach (var fileEntry in projectTemplate.Manifest)
|
||||
{
|
||||
var path = fileEntry.Path;
|
||||
var archiveEntry = archive.GetEntry(path);
|
||||
|
||||
if (archiveEntry is null)
|
||||
{
|
||||
Logger.LogError("Project template missing file: '{File}' {TemplateUri}", path, uri);
|
||||
return;
|
||||
}
|
||||
|
||||
if (path.EndsWith('/'))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
using var reader = new StreamReader(archiveEntry.Open());
|
||||
fileEntry.Text = reader.ReadToEnd();
|
||||
}
|
||||
|
||||
Register(projectTemplate);
|
||||
}
|
||||
catch (InvalidDataException)
|
||||
{
|
||||
Logger.LogError("URI not a Zip archive: {TemplateUri}", uri);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
while (e.InnerException != null)
|
||||
{
|
||||
e = e.InnerException;
|
||||
}
|
||||
|
||||
if (e is DirectoryNotFoundException || e is FileNotFoundException)
|
||||
{
|
||||
Logger.LogError("URI not found: {TemplateUri}", uri);
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger.LogError(
|
||||
e,
|
||||
"Unexpected error [{Exception}[{Error}]]: {TemplateUri}",
|
||||
e.GetType(),
|
||||
e.Message,
|
||||
uri);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private T ParseZipEntry<T>(ZipArchiveEntry entry)
|
||||
{
|
||||
if (entry is null)
|
||||
{
|
||||
return default(T);
|
||||
}
|
||||
|
||||
using var reader = new StreamReader(entry.Open());
|
||||
var text = reader.ReadToEnd();
|
||||
Logger.LogDebug("{Path}:\n{Text}", entry.FullName, text);
|
||||
return new DeserializerBuilder().WithNamingConvention(CamelCaseNamingConvention.Instance)
|
||||
.Build().Deserialize<T>(text);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,2 +1,2 @@
|
|||
# CodeCoverage
|
||||
coverage.opencover.xml
|
||||
# code coverage
|
||||
coverage*.*
|
||||
|
|
|
@ -1,24 +1,21 @@
|
|||
<Project>
|
||||
|
||||
<Import Project="$([MSBuild]::GetPathOfFileAbove('Directory.Build.props', '$(MSBuildThisFileDirectory)../'))" />
|
||||
<Import Project="$([MSBuild]::GetPathOfFileAbove('Directory.Build.props', '$(MSBuildThisFileDirectory)../'))" />
|
||||
|
||||
<PropertyGroup>
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="coverlet.collector" Version="1.3.0" />
|
||||
<PackageReference Include="coverlet.msbuild" Version="2.9.0" />
|
||||
<PackageReference Include="FluentAssertions" Version="5.10.3" />
|
||||
<PackageReference Include="FluentAssertions.Json" Version="5.5.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.5.0" />
|
||||
<PackageReference Include="Moq" Version="4.14.5" />
|
||||
<PackageReference Include="xunit" Version="2.4.0" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.0" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="coverlet.collector" Version="1.3.0" />
|
||||
<PackageReference Include="coverlet.msbuild" Version="2.9.0" />
|
||||
<PackageReference Include="FluentAssertions" Version="5.10.3" />
|
||||
<PackageReference Include="FluentAssertions.Json" Version="5.5.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="3.1.7" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.5.0" />
|
||||
<PackageReference Include="Moq" Version="4.14.5" />
|
||||
<PackageReference Include="xunit" Version="2.4.0" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.0" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
<!--
|
||||
vim: ft=xml
|
||||
-->
|
||||
|
|
|
@ -0,0 +1,108 @@
|
|||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using FluentAssertions;
|
||||
using Microsoft.AspNetCore.Mvc.Testing;
|
||||
using Xunit;
|
||||
|
||||
namespace Steeltoe.InitializrApi.Test.Integration
|
||||
{
|
||||
public class HttpTests : IClassFixture<WebApplicationFactory<Startup>>
|
||||
{
|
||||
/* ----------------------------------------------------------------- *
|
||||
* positive tests *
|
||||
* ----------------------------------------------------------------- */
|
||||
|
||||
/* ----------------------------------------------------------------- *
|
||||
* negative tests *
|
||||
* ----------------------------------------------------------------- */
|
||||
|
||||
[Fact]
|
||||
public async Task Get_Unknown_Path_Should_Return_404_Not_Found()
|
||||
{
|
||||
// Act
|
||||
var response = await HttpClient.GetAsync("no such path");
|
||||
|
||||
// Assert
|
||||
response.StatusCode.Should().Be(HttpStatusCode.NotFound);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(AboutEndpoint)]
|
||||
[InlineData(ConfigurationEndpoint)]
|
||||
[InlineData(ProjectEndpoint)]
|
||||
public async Task Post_Should_Return_405_Method_Not_Allowed(string path)
|
||||
{
|
||||
// Act
|
||||
var response = await HttpClient.PostAsync(path, new StringContent(""));
|
||||
|
||||
// Assert
|
||||
response.StatusCode.Should().Be(HttpStatusCode.MethodNotAllowed);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(AboutEndpoint)]
|
||||
[InlineData(ConfigurationEndpoint)]
|
||||
[InlineData(ProjectEndpoint)]
|
||||
public async Task Put_Should_Return_405_Method_Not_Allowed(string path)
|
||||
{
|
||||
// Act
|
||||
var response = await HttpClient.PutAsync(path, new StringContent(""));
|
||||
|
||||
// Assert
|
||||
response.StatusCode.Should().Be(HttpStatusCode.MethodNotAllowed);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(AboutEndpoint)]
|
||||
[InlineData(ConfigurationEndpoint)]
|
||||
[InlineData(ProjectEndpoint)]
|
||||
public async Task Patch_Should_Return_405_Method_Not_Allowed(string path)
|
||||
{
|
||||
// Act
|
||||
var response = await HttpClient.PatchAsync(path, new StringContent(""));
|
||||
|
||||
// Assert
|
||||
response.StatusCode.Should().Be(HttpStatusCode.MethodNotAllowed);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData(AboutEndpoint)]
|
||||
[InlineData(ConfigurationEndpoint)]
|
||||
[InlineData(ProjectEndpoint)]
|
||||
public async Task Delete_Should_Return_405_Method_Not_Allowed(string path)
|
||||
{
|
||||
// Act
|
||||
var response = await HttpClient.DeleteAsync(path);
|
||||
|
||||
// Assert
|
||||
response.StatusCode.Should().Be(HttpStatusCode.MethodNotAllowed);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------- *
|
||||
* constants *
|
||||
* ----------------------------------------------------------------- */
|
||||
|
||||
private const string AboutEndpoint = "/api/about";
|
||||
|
||||
private const string ConfigurationEndpoint = "/api/config";
|
||||
|
||||
private const string ProjectEndpoint = "/api/project";
|
||||
|
||||
/* ----------------------------------------------------------------- *
|
||||
* fields *
|
||||
* ----------------------------------------------------------------- */
|
||||
|
||||
private HttpClient HttpClient { get; }
|
||||
|
||||
/* ----------------------------------------------------------------- *
|
||||
* constructors
|
||||
* ----------------------------------------------------------------- */
|
||||
|
||||
public HttpTests(WebApplicationFactory<Startup> fixture)
|
||||
{
|
||||
HttpClient = fixture.CreateClient();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -5,12 +5,16 @@
|
|||
using FluentAssertions;
|
||||
using Xunit;
|
||||
|
||||
namespace Steeltoe.InitializrApi.Test
|
||||
namespace Steeltoe.InitializrApi.Test.Integration
|
||||
{
|
||||
public class ProgramTest
|
||||
public class ProgramTests
|
||||
{
|
||||
/* ----------------------------------------------------------------- *
|
||||
* positive tests *
|
||||
* ----------------------------------------------------------------- */
|
||||
|
||||
[Fact]
|
||||
public void About()
|
||||
public void About_Should_Contain_About_Details()
|
||||
{
|
||||
var about = Program.About;
|
||||
about.Name.Should().Be("Steeltoe.InitializrApi");
|
||||
|
@ -22,5 +26,8 @@ namespace Steeltoe.InitializrApi.Test
|
|||
about.Commit.Length.Should().Be(40); // Git SHA string length
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------- *
|
||||
* negative tests *
|
||||
* ----------------------------------------------------------------- */
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="..\Directory.Build.props">
|
||||
<Link>Directory.Build.props</Link>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\InitializrApi\Steeltoe.InitializrApi.csproj" />
|
||||
<ProjectReference Include="..\InitializrApi.Test.Utils\Steeltoe.InitializrApi.Test.Utils.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="YamlDotNet" Version="8.1.2" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
|
@ -0,0 +1,77 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using FluentAssertions;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using Moq;
|
||||
using Steeltoe.InitializrApi.Archivers;
|
||||
using Steeltoe.InitializrApi.Services;
|
||||
using Xunit;
|
||||
|
||||
namespace Steeltoe.InitializrApi.Test.Unit.Archivers
|
||||
{
|
||||
public class ArchiverRegistryTests
|
||||
{
|
||||
/* ----------------------------------------------------------------- *
|
||||
* positive tests *
|
||||
* ----------------------------------------------------------------- */
|
||||
|
||||
[Fact]
|
||||
public void Zip_Format_Should_Return_ZipArchiver()
|
||||
{
|
||||
// Arrange
|
||||
var registry = new ArchiverRegistry(new NullLogger<ArchiverRegistry>());
|
||||
registry.Initialize();
|
||||
|
||||
// Act
|
||||
var archiver = registry.Lookup("application/zip");
|
||||
|
||||
// Assert
|
||||
archiver.Should().NotBeNull();
|
||||
archiver.Should().BeOfType<ZipArchiver>();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Initialize_Should_Reset_State()
|
||||
{
|
||||
// Arrange
|
||||
var registry = new ArchiverRegistry(new NullLogger<ArchiverRegistry>());
|
||||
registry.Initialize();
|
||||
var myArchiver = new Mock<IArchiver>();
|
||||
myArchiver.Setup(a => a.GetMimeType()).Returns("mytype");
|
||||
registry.Register(myArchiver.Object);
|
||||
|
||||
// Act
|
||||
var archiver = registry.Lookup("mytype");
|
||||
|
||||
// Assert
|
||||
archiver.Should().NotBeNull();
|
||||
|
||||
// Act
|
||||
registry.Initialize();
|
||||
archiver = registry.Lookup("mytype");
|
||||
|
||||
// Assert
|
||||
archiver.Should().BeNull();
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------- *
|
||||
* negative tests *
|
||||
* ----------------------------------------------------------------- */
|
||||
|
||||
[Fact]
|
||||
public void Unknown_Format_Should_Return_Null()
|
||||
{
|
||||
// Arrange
|
||||
var registry = new ArchiverRegistry(new NullLogger<ArchiverRegistry>());
|
||||
registry.Initialize();
|
||||
|
||||
// Act
|
||||
var archiver = registry.Lookup("unknown");
|
||||
|
||||
// Assert
|
||||
archiver.Should().BeNull();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,117 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using FluentAssertions;
|
||||
using Steeltoe.InitializrApi.Archivers;
|
||||
using Steeltoe.InitializrApi.Models;
|
||||
using Xunit;
|
||||
|
||||
namespace Steeltoe.InitializrApi.Test.Unit.Archivers
|
||||
{
|
||||
public class ZipArchiverTests
|
||||
{
|
||||
/* ----------------------------------------------------------------- *
|
||||
* positive tests *
|
||||
* ----------------------------------------------------------------- */
|
||||
|
||||
[Fact]
|
||||
public void ToStream_Should_Create_Zip_Archive()
|
||||
{
|
||||
// Arrange
|
||||
var archiver = new ZipArchiver();
|
||||
var files = new FileEntry[0];
|
||||
|
||||
// Act
|
||||
var buf = archiver.ToBytes(files);
|
||||
|
||||
// Assert
|
||||
new ZipArchive(new MemoryStream(buf)).Should().BeOfType<ZipArchive>();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ToStream_Should_Archive_File_Contents()
|
||||
{
|
||||
// Arrange
|
||||
var archiver = new ZipArchiver();
|
||||
var files = new[]
|
||||
{
|
||||
new FileEntry { Path = "d1/f1", Text = "f1 stuff" },
|
||||
};
|
||||
|
||||
|
||||
// Act
|
||||
var buf = archiver.ToBytes(files);
|
||||
|
||||
// Assert
|
||||
var zip = new ZipArchive(new MemoryStream(buf));
|
||||
using var entries = zip.Entries.GetEnumerator();
|
||||
entries.MoveNext().Should().BeTrue();
|
||||
var entry = entries.Current;
|
||||
Assert.NotNull(entry);
|
||||
entry.Name.Should().Be("f1");
|
||||
entry.FullName.Should().Be("d1/f1");
|
||||
using var reader = new StreamReader(entry.Open());
|
||||
reader.ReadToEnd().Should().Be("f1 stuff");
|
||||
entries.MoveNext().Should().BeFalse();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ToStream_Should_Archive_Directories()
|
||||
{
|
||||
// Arrange
|
||||
var archiver = new ZipArchiver();
|
||||
var files = new[]
|
||||
{
|
||||
new FileEntry { Path = "d1/d2" },
|
||||
};
|
||||
|
||||
// Act
|
||||
var buf = archiver.ToBytes(files);
|
||||
|
||||
// Assert
|
||||
var zip = new ZipArchive(new MemoryStream(buf));
|
||||
using var entries = zip.Entries.GetEnumerator();
|
||||
entries.MoveNext().Should().BeTrue();
|
||||
var entry = entries.Current;
|
||||
Assert.NotNull(entry);
|
||||
entry.Name.Should().Be("d2");
|
||||
entry.FullName.Should().Be("d1/d2");
|
||||
using var reader = new StreamReader(entry.Open());
|
||||
reader.ReadToEnd().Should().BeEmpty();
|
||||
entries.MoveNext().Should().BeFalse();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetMimeType_Should_Be_application_zip()
|
||||
{
|
||||
// Arrange
|
||||
var archiver = new ZipArchiver();
|
||||
|
||||
// Act
|
||||
var mimeType = archiver.GetMimeType();
|
||||
|
||||
// Assert
|
||||
mimeType.Should().Be("application/zip");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetFileExtension_Should_Be_zip()
|
||||
{
|
||||
// Arrange
|
||||
var archiver = new ZipArchiver();
|
||||
|
||||
// Act
|
||||
var ext = archiver.GetFileExtension();
|
||||
|
||||
// Assert
|
||||
ext.Should().Be(".zip");
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------- *
|
||||
* negative tests *
|
||||
* ----------------------------------------------------------------- */
|
||||
}
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Moq;
|
||||
using Steeltoe.InitializrApi.Configuration;
|
||||
using Steeltoe.InitializrApi.Models;
|
||||
using Steeltoe.InitializrApi.Test.Utils;
|
||||
using Xunit;
|
||||
|
||||
namespace Steeltoe.InitializrApi.Test.Unit.Configuration
|
||||
{
|
||||
public class InitializrConfigServiceTests
|
||||
{
|
||||
/* ----------------------------------------------------------------- *
|
||||
* positive tests *
|
||||
* ----------------------------------------------------------------- */
|
||||
|
||||
/* ----------------------------------------------------------------- *
|
||||
* negative tests *
|
||||
* ----------------------------------------------------------------- */
|
||||
|
||||
[Fact]
|
||||
public void Null_Project_Metadata_Should_Log_An_Error()
|
||||
{
|
||||
// Arrange
|
||||
var cfg = new InitializrConfig
|
||||
{
|
||||
ProjectTemplates = new ProjectTemplateConfiguration[0],
|
||||
};
|
||||
var configOptions = new Mock<IOptions<InitializrConfig>>();
|
||||
configOptions.Setup(opts => opts.Value).Returns(cfg);
|
||||
var logger = new Mock<ILogger<InitializrConfigService>>();
|
||||
var service = new InitializrConfigService(configOptions.Object, logger.Object);
|
||||
|
||||
// Act
|
||||
service.Initialize();
|
||||
|
||||
// Assert
|
||||
logger.VerifyLog(LogLevel.Error, "Project metadata missing.");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Null_Project_Templates_Configuration_Should_Log_An_Error()
|
||||
{
|
||||
// Arrange
|
||||
var cfg = new InitializrConfig
|
||||
{
|
||||
ProjectMetadata = new ProjectMetadata(),
|
||||
};
|
||||
cfg.ProjectMetadata = new ProjectMetadata();
|
||||
var configOptions = new Mock<IOptions<InitializrConfig>>();
|
||||
configOptions.Setup(opts => opts.Value).Returns(cfg);
|
||||
var logger = new Mock<ILogger<InitializrConfigService>>();
|
||||
var service = new InitializrConfigService(configOptions.Object, logger.Object);
|
||||
|
||||
// Act
|
||||
service.Initialize();
|
||||
|
||||
// Assert
|
||||
logger.VerifyLog(LogLevel.Error, "Project templates configuration missing.");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using FluentAssertions;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using Steeltoe.InitializrApi.Controllers;
|
||||
using Steeltoe.InitializrApi.Models;
|
||||
using Xunit;
|
||||
|
||||
namespace Steeltoe.InitializrApi.Test.Unit.Controllers
|
||||
{
|
||||
public class AboutControllerTests
|
||||
{
|
||||
/* ----------------------------------------------------------------- *
|
||||
* positive tests *
|
||||
* ----------------------------------------------------------------- */
|
||||
|
||||
[Fact]
|
||||
public void GetAbout_Should_Return_About()
|
||||
{
|
||||
// Arrange
|
||||
var controller = new AboutController(new NullLogger<AboutController>());
|
||||
|
||||
// Act
|
||||
var result = controller.GetAbout();
|
||||
|
||||
// Assert
|
||||
var indexResult = Assert.IsType<OkObjectResult>(result);
|
||||
indexResult.Value.Should().BeOfType<About>();
|
||||
var about = Assert.IsType<About>(indexResult.Value);
|
||||
about.Name.Should().Be("Steeltoe.InitializrApi");
|
||||
about.Vendor.Should().Be("SteeltoeOSS/VMware");
|
||||
about.Url.Should().Be("https://github.com/SteeltoeOSS/InitializrApi/");
|
||||
about.Version.Should().StartWith("0.7.0");
|
||||
about.Commit.Should().NotBeNullOrWhiteSpace();
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------- *
|
||||
* negative tests *
|
||||
* ----------------------------------------------------------------- */
|
||||
}
|
||||
}
|
|
@ -0,0 +1,83 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using FluentAssertions;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using Moq;
|
||||
using Steeltoe.InitializrApi.Controllers;
|
||||
using Steeltoe.InitializrApi.Models;
|
||||
using Steeltoe.InitializrApi.Services;
|
||||
using Xunit;
|
||||
|
||||
namespace Steeltoe.InitializrApi.Test.Unit.Controllers
|
||||
{
|
||||
public class ConfigControllerTests
|
||||
{
|
||||
/* ----------------------------------------------------------------- *
|
||||
* positive tests *
|
||||
* ----------------------------------------------------------------- */
|
||||
|
||||
[Fact]
|
||||
public void GetInitializrApiConfiguration_Should_Return_InitializrApiConfiguration()
|
||||
{
|
||||
// Arrange
|
||||
var config = new InitializrConfig();
|
||||
var configService = new Mock<IInitializrConfigService>();
|
||||
configService.Setup(repo => repo.GetInitializrConfig()).Returns(config);
|
||||
var controller = new ConfigController(configService.Object, new NullLogger<ConfigController>());
|
||||
|
||||
// Act
|
||||
var result = controller.GetInitializrConfiguration();
|
||||
|
||||
// Assert
|
||||
var indexResult = Assert.IsType<OkObjectResult>(result);
|
||||
indexResult.Value.Should().BeSameAs(config);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetProjectMetadata_Should_Return_ProjectMetadata()
|
||||
{
|
||||
// Arrange
|
||||
var config = new InitializrConfig
|
||||
{
|
||||
ProjectMetadata = new ProjectMetadata(),
|
||||
};
|
||||
var configService = new Mock<IInitializrConfigService>();
|
||||
configService.Setup(repo => repo.GetInitializrConfig()).Returns(config);
|
||||
var controller = new ConfigController(configService.Object, new NullLogger<ConfigController>());
|
||||
|
||||
// Act
|
||||
var result = controller.GetProjectMetadata();
|
||||
|
||||
// Assert
|
||||
var indexResult = Assert.IsType<OkObjectResult>(result);
|
||||
indexResult.Value.Should().BeSameAs(config.ProjectMetadata);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GetProjectTemplateConfigurations_Should_Return_ProjectTemplateConfigurations()
|
||||
{
|
||||
// Arrange
|
||||
var config = new InitializrConfig
|
||||
{
|
||||
ProjectTemplates = new ProjectTemplateConfiguration[0],
|
||||
};
|
||||
var configService = new Mock<IInitializrConfigService>();
|
||||
configService.Setup(repo => repo.GetInitializrConfig()).Returns(config);
|
||||
var controller = new ConfigController(configService.Object, new NullLogger<ConfigController>());
|
||||
|
||||
// Act
|
||||
var result = controller.GetProjectTemplatesConfig();
|
||||
|
||||
// Assert
|
||||
var indexResult = Assert.IsType<OkObjectResult>(result);
|
||||
indexResult.Value.Should().BeSameAs(config.ProjectTemplates);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------- *
|
||||
* negative tests *
|
||||
* ----------------------------------------------------------------- */
|
||||
}
|
||||
}
|
|
@ -0,0 +1,311 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Text;
|
||||
using FluentAssertions;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using Moq;
|
||||
using Steeltoe.InitializrApi.Archivers;
|
||||
using Steeltoe.InitializrApi.Controllers;
|
||||
using Steeltoe.InitializrApi.Models;
|
||||
using Steeltoe.InitializrApi.Services;
|
||||
using Xunit;
|
||||
|
||||
namespace Steeltoe.InitializrApi.Test.Unit.Controllers
|
||||
{
|
||||
public class ProjectControllerTests
|
||||
{
|
||||
/* ----------------------------------------------------------------- *
|
||||
* positive tests *
|
||||
* ----------------------------------------------------------------- */
|
||||
|
||||
[Fact]
|
||||
public void Zip_Archive_Format_Should_Return_Zip_Archive()
|
||||
{
|
||||
// Arrange
|
||||
var archiverRegistry = new Mock<IArchiverRegistry>();
|
||||
archiverRegistry.Setup(reg => reg.Lookup(It.Is<string>(s => s.Equals("application/zip"))))
|
||||
.Returns(new ZipArchiver());
|
||||
var controller = new ProjectControllerBuilder().WithArchiverRegistry(archiverRegistry.Object).Build();
|
||||
var spec = new ProjectSpec { ArchiveMimeType = "application/zip" };
|
||||
|
||||
// Act
|
||||
var unknown = controller.GetProjectArchive(spec);
|
||||
|
||||
// Assert
|
||||
var result = Assert.IsType<FileContentResult>(unknown);
|
||||
result.ContentType.Should().Be("application/zip");
|
||||
result.FileDownloadName.Should().EndWith(".zip");
|
||||
var stream = new MemoryStream(result.FileContents);
|
||||
new ZipArchive(stream).Should().BeOfType<ZipArchive>();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Configuration_Should_Specify_Defaults()
|
||||
{
|
||||
// Arrange
|
||||
var config = new InitializrConfig
|
||||
{
|
||||
ProjectMetadata = new ProjectMetadata
|
||||
{
|
||||
Name = new ProjectMetadata.Text { Default = "my name" },
|
||||
Description = new ProjectMetadata.Text { Default = "my description" },
|
||||
Namespace = new ProjectMetadata.Text { Default = "my namespace" },
|
||||
SteeltoeVersion = new ProjectMetadata.SingleSelectList { Default = "my steeltoe version" },
|
||||
DotNetFramework = new ProjectMetadata.SingleSelectList { Default = "my dotnet framework" },
|
||||
DotNetTemplate = new ProjectMetadata.SingleSelectList { Default = "my dotnet template" },
|
||||
Language = new ProjectMetadata.SingleSelectList { Default = "my language" },
|
||||
ArchiveMimeType = new ProjectMetadata.SingleSelectList { Default = "application/myarchive" },
|
||||
Dependencies = new ProjectMetadata.GroupList { Default = "dep1,dep2" },
|
||||
},
|
||||
};
|
||||
var controller = new ProjectControllerBuilder()
|
||||
.WithInitializrConfiguration(config)
|
||||
.Build();
|
||||
|
||||
// Act
|
||||
var unknown = controller.GetProjectArchive(new ProjectSpec());
|
||||
|
||||
// Assert
|
||||
var result = Assert.IsType<FileContentResult>(unknown);
|
||||
using var reader = new StreamReader(new MemoryStream(result.FileContents));
|
||||
reader.ReadLine().Should().Be("name=my name");
|
||||
reader.ReadLine().Should().Be("description=my description");
|
||||
reader.ReadLine().Should().Be("namespace=my namespace");
|
||||
reader.ReadLine().Should().Be("steeltoe version=my steeltoe version");
|
||||
reader.ReadLine().Should().Be("dotnet framework=my dotnet framework");
|
||||
reader.ReadLine().Should().Be("dotnet template=my dotnet template");
|
||||
reader.ReadLine().Should().Be("language=my language");
|
||||
reader.ReadLine().Should().Be("archive mime type=application/myarchive");
|
||||
reader.ReadLine().Should().Be("dependencies=dep1,dep2");
|
||||
reader.ReadLine().Should().BeNull();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Dependencies_Should_Be_Case_Corrected()
|
||||
{
|
||||
// Arrange
|
||||
var config = new InitializrConfig
|
||||
{
|
||||
ProjectMetadata = new ProjectMetadata
|
||||
{
|
||||
Dependencies = new ProjectMetadata.GroupList
|
||||
{
|
||||
Values = new []
|
||||
{
|
||||
new ProjectMetadata.Group
|
||||
{
|
||||
Values = new []
|
||||
{
|
||||
new ProjectMetadata.GroupItem
|
||||
{
|
||||
Id = "CamelCaseDep",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
var spec = new ProjectSpec
|
||||
{
|
||||
ArchiveMimeType = "application/myarchive",
|
||||
Dependencies = "unknowndep,camelcasedep",
|
||||
};
|
||||
var controller = new ProjectControllerBuilder()
|
||||
.WithInitializrConfiguration(config)
|
||||
.Build();
|
||||
|
||||
// Act
|
||||
var unknown = controller.GetProjectArchive(spec);
|
||||
|
||||
// Assert
|
||||
var result = Assert.IsType<FileContentResult>(unknown);
|
||||
using var reader = new StreamReader(new MemoryStream(result.FileContents));
|
||||
var body = reader.ReadToEnd();
|
||||
body.Should().Contain("dependencies=unknowndep,CamelCaseDep");
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------- *
|
||||
* negative tests *
|
||||
* ----------------------------------------------------------------- */
|
||||
|
||||
[Fact]
|
||||
public void No_Template_Found_Should_Return_404_Page_Not_Found()
|
||||
{
|
||||
// Arrange
|
||||
var controller = new ProjectControllerBuilder().Build();
|
||||
var spec = new ProjectSpec { Name = "nosuchtemplate" };
|
||||
|
||||
// Act
|
||||
var unknown = controller.GetProjectArchive(spec);
|
||||
|
||||
// Assert
|
||||
var result = Assert.IsType<NotFoundObjectResult>(unknown);
|
||||
result.Value.ToString().Should()
|
||||
.Be("No such project for spec: [name=nosuchtemplate,archiveMimeType=application/myarchive]");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Unknown_Archive_Format_Should_Return_404_Page_Not_Found()
|
||||
{
|
||||
// Arrange
|
||||
var controller = new ProjectControllerBuilder().Build();
|
||||
var spec = new ProjectSpec { ArchiveMimeType = "application/nosuchformat" };
|
||||
|
||||
// Act
|
||||
var unknown = controller.GetProjectArchive(spec);
|
||||
|
||||
// Assert
|
||||
var result = Assert.IsType<NotFoundObjectResult>(unknown);
|
||||
result.Value.ToString().Should().Be("Archive mime type 'application/nosuchformat' not found.");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Null_Archive_Format_Should_Return_500_Internal_Server_Error()
|
||||
{
|
||||
// Arrange
|
||||
var spec = new ProjectSpec();
|
||||
var config = new InitializrConfig { ProjectTemplates = new ProjectTemplateConfiguration[0] };
|
||||
var controller = new ProjectControllerBuilder().WithInitializrConfiguration(config).Build();
|
||||
|
||||
// Act
|
||||
var unknown = controller.GetProjectArchive(spec);
|
||||
|
||||
// Assert
|
||||
var result = Assert.IsType<ObjectResult>(unknown);
|
||||
result.StatusCode.Should().Be(StatusCodes.Status500InternalServerError);
|
||||
result.Value.Should().Be("Default archive mime type not configured.");
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------- *
|
||||
* test helpers *
|
||||
* ----------------------------------------------------------------- */
|
||||
|
||||
class ProjectControllerBuilder
|
||||
{
|
||||
private InitializrConfig _config;
|
||||
|
||||
private IProjectGenerator _generator;
|
||||
|
||||
private IArchiverRegistry _registry;
|
||||
|
||||
internal ProjectController Build()
|
||||
{
|
||||
if (_config is null)
|
||||
{
|
||||
_config = new InitializrConfig
|
||||
{
|
||||
ProjectMetadata = new ProjectMetadata
|
||||
{
|
||||
ArchiveMimeType = new ProjectMetadata.SingleSelectList
|
||||
{
|
||||
Default = "application/myarchive",
|
||||
},
|
||||
},
|
||||
ProjectTemplates = new ProjectTemplateConfiguration[0],
|
||||
};
|
||||
}
|
||||
|
||||
if (_generator is null)
|
||||
{
|
||||
_generator = new TestProjectGenerator();
|
||||
}
|
||||
|
||||
if (_registry is null)
|
||||
{
|
||||
var mock = new Mock<IArchiverRegistry>();
|
||||
mock.Setup(reg => reg.Lookup(It.Is<string>(s => s.Equals("application/myarchive"))))
|
||||
.Returns(new TestArchiver());
|
||||
_registry = mock.Object;
|
||||
}
|
||||
|
||||
var configurationService = new Mock<IInitializrConfigService>();
|
||||
configurationService.Setup(svc => svc.GetInitializrConfig()).Returns(_config);
|
||||
var logger = new NullLogger<ProjectController>();
|
||||
var projectController =
|
||||
new ProjectController(configurationService.Object, _generator, _registry, logger)
|
||||
{
|
||||
ControllerContext =
|
||||
{
|
||||
HttpContext = new DefaultHttpContext()
|
||||
}
|
||||
};
|
||||
return projectController;
|
||||
}
|
||||
|
||||
internal ProjectControllerBuilder WithInitializrConfiguration(InitializrConfig config)
|
||||
{
|
||||
_config = config;
|
||||
return this;
|
||||
}
|
||||
|
||||
internal ProjectControllerBuilder WithArchiverRegistry(IArchiverRegistry registry)
|
||||
{
|
||||
_registry = registry;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
private class TestProjectGenerator : IProjectGenerator
|
||||
{
|
||||
public Project GenerateProject(ProjectSpec spec)
|
||||
{
|
||||
if (spec.Name != null && spec.Name.Equals("nosuchtemplate"))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
var project = new Project();
|
||||
project.FileEntries.Add(new FileEntry { Path = "name", Text = spec.Name ?? "<na>" });
|
||||
project.FileEntries.Add(new FileEntry { Path = "description", Text = spec.Description ?? "<na>" });
|
||||
project.FileEntries.Add(new FileEntry { Path = "namespace", Text = spec.Namespace ?? "<na>" });
|
||||
project.FileEntries.Add(new FileEntry
|
||||
{ Path = "steeltoe version", Text = spec.SteeltoeVersion ?? "<na>" });
|
||||
project.FileEntries.Add(new FileEntry
|
||||
{ Path = "dotnet framework", Text = spec.DotNetFramework ?? "<na>" });
|
||||
project.FileEntries.Add(
|
||||
new FileEntry { Path = "dotnet template", Text = spec.DotNetTemplate ?? "<na>" });
|
||||
project.FileEntries.Add(new FileEntry { Path = "language", Text = spec.Language ?? "<na>" });
|
||||
project.FileEntries.Add(new FileEntry
|
||||
{ Path = "archive mime type", Text = spec.ArchiveMimeType ?? "<na>" });
|
||||
project.FileEntries.Add(new FileEntry { Path = "dependencies", Text = spec.Dependencies ?? "<na>" });
|
||||
return project;
|
||||
}
|
||||
}
|
||||
|
||||
private class TestArchiver : IArchiver
|
||||
{
|
||||
public byte[] ToBytes(IEnumerable<FileEntry> fileEntries)
|
||||
{
|
||||
var buf = new StringBuilder();
|
||||
foreach (var fileEntry in fileEntries)
|
||||
{
|
||||
buf.Append(fileEntry.Path)
|
||||
.Append('=')
|
||||
.Append(fileEntry.Text)
|
||||
.Append(Environment.NewLine);
|
||||
}
|
||||
|
||||
return Encoding.UTF8.GetBytes(buf.ToString());
|
||||
}
|
||||
|
||||
public string GetMimeType()
|
||||
{
|
||||
return "application/myarchive";
|
||||
}
|
||||
|
||||
public string GetFileExtension()
|
||||
{
|
||||
return ".myext";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,161 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using FluentAssertions;
|
||||
using Steeltoe.InitializrApi.Expressions;
|
||||
using Xunit;
|
||||
|
||||
namespace Steeltoe.InitializrApi.Test.Unit.Expressions
|
||||
{
|
||||
public class ExpressionParserTests
|
||||
{
|
||||
/* ----------------------------------------------------------------- *
|
||||
* positive tests *
|
||||
* ----------------------------------------------------------------- */
|
||||
|
||||
[Fact]
|
||||
public void True_Parameter_Should_Evaluate_To_True()
|
||||
{
|
||||
// Arrange
|
||||
var expression = new Expression<bool>("tDep");
|
||||
var parameters = new Dictionary<string, object>
|
||||
{
|
||||
{ "tDep", true },
|
||||
};
|
||||
|
||||
// Act
|
||||
var result = expression.Evaluate(parameters);
|
||||
|
||||
// Assert
|
||||
result.Should().Be(true);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void False_Parameter_Should_Evaluate_To_False()
|
||||
{
|
||||
// Arrange
|
||||
var expression = new Expression<bool>("fDep");
|
||||
var parameters = new Dictionary<string, object>
|
||||
{
|
||||
{ "fDep", false },
|
||||
};
|
||||
|
||||
// Act
|
||||
var result = expression.Evaluate(parameters);
|
||||
|
||||
// Assert
|
||||
result.Should().Be(false);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Null_Parameter_Should_Evaluate_To_False()
|
||||
{
|
||||
// Arrange
|
||||
var expression = new Expression<bool>("nDep");
|
||||
var parameters = new Dictionary<string, object>();
|
||||
|
||||
// Act
|
||||
var result = expression.Evaluate(parameters);
|
||||
|
||||
// Assert
|
||||
result.Should().Be(false);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Or_Operand_Should_Should_Evaluate_Per_Boolean_Rules()
|
||||
{
|
||||
// Arrange
|
||||
var expressionTt = new Expression<bool>("t1Dep || t2Dep");
|
||||
var expressionTf = new Expression<bool>("t1Dep || f1Dep");
|
||||
var expressionTn = new Expression<bool>("t1Dep || n1Dep");
|
||||
var expressionFt = new Expression<bool>("f1Dep || t1Dep");
|
||||
var expressionFf = new Expression<bool>("f1Dep || f2Dep");
|
||||
var expressionFn = new Expression<bool>("f1Dep || n1Dep");
|
||||
var expressionNt = new Expression<bool>("n1Dep || t1Dep");
|
||||
var expressionNf = new Expression<bool>("n1Dep || f1Dep");
|
||||
var expressionNn = new Expression<bool>("n1Dep || n2Dep");
|
||||
var parameters = new Dictionary<string, object>
|
||||
{
|
||||
{ "t1Dep", true },
|
||||
{ "t2Dep", true },
|
||||
{ "f1Dep", false },
|
||||
{ "f2Dep", false },
|
||||
};
|
||||
|
||||
// Act
|
||||
var resultTt = expressionTt.Evaluate(parameters);
|
||||
var resultTf = expressionTf.Evaluate(parameters);
|
||||
var resultTn = expressionTn.Evaluate(parameters);
|
||||
var resultFt = expressionFt.Evaluate(parameters);
|
||||
var resultFf = expressionFf.Evaluate(parameters);
|
||||
var resultFn = expressionFn.Evaluate(parameters);
|
||||
var resultNt = expressionNt.Evaluate(parameters);
|
||||
var resultNf = expressionNf.Evaluate(parameters);
|
||||
var resultNn = expressionNn.Evaluate(parameters);
|
||||
|
||||
// Assert
|
||||
resultTt.Should().Be(true);
|
||||
resultTf.Should().Be(true);
|
||||
resultTn.Should().Be(true);
|
||||
resultFt.Should().Be(true);
|
||||
resultFf.Should().Be(false);
|
||||
resultFn.Should().Be(false);
|
||||
resultNt.Should().Be(true);
|
||||
resultNf.Should().Be(false);
|
||||
resultNn.Should().Be(false);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Complex_Or_Operand_Should_Should_Evaluate_Per_Boolean_Rules()
|
||||
{
|
||||
// Arrange
|
||||
var expressionFff = new Expression<bool>("f1Dep || f2Dep || f3Dep");
|
||||
var expressionNnn = new Expression<bool>("n1Dep || n2Dep || n3Dep");
|
||||
var expressionTtt = new Expression<bool>("t1Dep || t2Dep || t3Dep");
|
||||
var expressionTfn = new Expression<bool>("t1Dep || f1Dep || n1Dep");
|
||||
var parameters = new Dictionary<string, object>
|
||||
{
|
||||
{ "t1Dep", true },
|
||||
{ "t2Dep", true },
|
||||
{ "t3Dep", true },
|
||||
{ "f1Dep", false },
|
||||
{ "f2Dep", false },
|
||||
{ "f3Dep", false },
|
||||
};
|
||||
|
||||
// Act
|
||||
var resultFff = expressionFff.Evaluate(parameters);
|
||||
var resultNnn = expressionNnn.Evaluate(parameters);
|
||||
var resultTtt = expressionTtt.Evaluate(parameters);
|
||||
var resultTfn = expressionTfn.Evaluate(parameters);
|
||||
|
||||
// Assert
|
||||
resultFff.Should().Be(false);
|
||||
resultNnn.Should().Be(false);
|
||||
resultTtt.Should().Be(true);
|
||||
resultTfn.Should().Be(true);
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------- *
|
||||
* negative tests *
|
||||
* ----------------------------------------------------------------- */
|
||||
|
||||
[Fact]
|
||||
public void Unexpected_Character_Should_Throw_Exception()
|
||||
{
|
||||
// Arrange
|
||||
|
||||
// Act
|
||||
Action act = () =>
|
||||
{
|
||||
var _ = new Expression<object>("@");
|
||||
};
|
||||
|
||||
// Assert
|
||||
act.Should().Throw<ExpressionException>().WithMessage("Unexpected character: '@'");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,230 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using FluentAssertions;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using Moq;
|
||||
using Steeltoe.InitializrApi.Generators;
|
||||
using Steeltoe.InitializrApi.Models;
|
||||
using Steeltoe.InitializrApi.Services;
|
||||
using Xunit;
|
||||
|
||||
namespace Steeltoe.InitializrApi.Test.Unit.Generators
|
||||
{
|
||||
public class StubbleProjectGeneratorTests
|
||||
{
|
||||
/* ----------------------------------------------------------------- *
|
||||
* positive tests *
|
||||
* ----------------------------------------------------------------- */
|
||||
|
||||
[Fact]
|
||||
public void GenerateProject_Should_Generate_A_Project()
|
||||
{
|
||||
// Arrange
|
||||
var spec = new ProjectSpec();
|
||||
var template = new ProjectTemplate { Manifest = new FileEntry[0] };
|
||||
var generator = new StubbleProjectGeneratorBuilder().WithProjectTemplate(template).Build();
|
||||
|
||||
// Act
|
||||
var project = generator.GenerateProject(spec);
|
||||
|
||||
// Assert
|
||||
project.Should().NotBeNull();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GenerateProject_Should_Render_Files()
|
||||
{
|
||||
// Arrange
|
||||
var spec = new ProjectSpec
|
||||
{
|
||||
Name = "my name",
|
||||
Description = "my description",
|
||||
Namespace = "my namespace",
|
||||
SteeltoeVersion = "my steeltoe version",
|
||||
DotNetFramework = "my dotnet framework",
|
||||
DotNetTemplate = "my dotnet template",
|
||||
Language = "my language",
|
||||
};
|
||||
var template = new ProjectTemplate
|
||||
{
|
||||
Manifest = new[]
|
||||
{
|
||||
new FileEntry { Path = "name", Text = "{{Name}}" },
|
||||
new FileEntry { Path = "description", Text = "{{Description}}" },
|
||||
new FileEntry { Path = "namespace", Text = "{{Namespace}}" },
|
||||
new FileEntry { Path = "steeltoe version", Text = "{{SteeltoeVersion}}" },
|
||||
new FileEntry { Path = "dotnet framework", Text = "{{DotNetFramework}}" },
|
||||
new FileEntry { Path = "dotnet template", Text = "{{DotNetTemplate}}" },
|
||||
new FileEntry { Path = "language", Text = "{{Language}}" },
|
||||
},
|
||||
};
|
||||
var generator = new StubbleProjectGeneratorBuilder().WithProjectTemplate(template).Build();
|
||||
|
||||
// Act
|
||||
var project = generator.GenerateProject(spec);
|
||||
|
||||
// Assert
|
||||
project.Should().NotBeNull();
|
||||
var i = 0;
|
||||
project.FileEntries[i++].Text.Should().Be("my name");
|
||||
project.FileEntries[i++].Text.Should().Be("my description");
|
||||
project.FileEntries[i++].Text.Should().Be("my namespace");
|
||||
project.FileEntries[i++].Text.Should().Be("my steeltoe version");
|
||||
project.FileEntries[i++].Text.Should().Be("my dotnet framework");
|
||||
project.FileEntries[i++].Text.Should().Be("my dotnet template");
|
||||
project.FileEntries[i++].Text.Should().Be("my language");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GenerateProject_Should_Render_Directories()
|
||||
{
|
||||
// Arrange
|
||||
var spec = new ProjectSpec();
|
||||
var template = new ProjectTemplate
|
||||
{
|
||||
Manifest = new[]
|
||||
{
|
||||
new FileEntry { Path = "d1/" },
|
||||
new FileEntry { Path = "d1/d2/" },
|
||||
},
|
||||
};
|
||||
var generator = new StubbleProjectGeneratorBuilder().WithProjectTemplate(template).Build();
|
||||
|
||||
// Act
|
||||
var project = generator.GenerateProject(spec);
|
||||
|
||||
// Assert
|
||||
project.Should().NotBeNull();
|
||||
project.FileEntries[0].Path.Should().Be("d1/");
|
||||
project.FileEntries[0].Text.Should().BeNull();
|
||||
project.FileEntries[1].Path.Should().Be("d1/d2/");
|
||||
project.FileEntries[1].Text.Should().BeNull();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GenerateProject_Should_Rename_Files()
|
||||
{
|
||||
// Arrange
|
||||
var spec = new ProjectSpec { Name = "newName" };
|
||||
var template = new ProjectTemplate
|
||||
{
|
||||
Manifest = new[]
|
||||
{
|
||||
new FileEntry { Path = "oldName", Rename = "{{Name}}" },
|
||||
},
|
||||
};
|
||||
var generator = new StubbleProjectGeneratorBuilder().WithProjectTemplate(template).Build();
|
||||
|
||||
// Act
|
||||
var project = generator.GenerateProject(spec);
|
||||
|
||||
// Assert
|
||||
project.Should().NotBeNull();
|
||||
project.FileEntries[0].Path.Should().Be("newName");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GenerateProject_Should_Omit_Files_If_Dependency_Not_Met()
|
||||
{
|
||||
// Arrange
|
||||
var spec = new ProjectSpec { Dependencies = "dep0,dep1" };
|
||||
var template = new ProjectTemplate
|
||||
{
|
||||
Manifest = new[]
|
||||
{
|
||||
new FileEntry { Path = "f0" },
|
||||
new FileEntry { Path = "f1", Dependencies = "dep0" },
|
||||
new FileEntry { Path = "f2", Dependencies = "dep1" },
|
||||
new FileEntry { Path = "f3", Dependencies = "dep0,dep1" },
|
||||
new FileEntry { Path = "f4", Dependencies = "dep2" },
|
||||
new FileEntry { Path = "f5", Dependencies = "dep0,dep2" },
|
||||
},
|
||||
};
|
||||
var generator = new StubbleProjectGeneratorBuilder().WithProjectTemplate(template).Build();
|
||||
|
||||
// Act
|
||||
var project = generator.GenerateProject(spec);
|
||||
|
||||
// Assert
|
||||
project.FileEntries.Count.Should().Be(5);
|
||||
var i = 0;
|
||||
project.FileEntries[i++].Path.Should().Be("f0");
|
||||
project.FileEntries[i++].Path.Should().Be("f1");
|
||||
project.FileEntries[i++].Path.Should().Be("f2");
|
||||
project.FileEntries[i++].Path.Should().Be("f3");
|
||||
project.FileEntries[i++].Path.Should().Be("f5");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void GenerateProject_Should_Evaluate_Parameter_Or_Expressions()
|
||||
{
|
||||
// Arrange
|
||||
var spec = new ProjectSpec { Dependencies = "dep1,dep2" };
|
||||
var template = new ProjectTemplate
|
||||
{
|
||||
Manifest = new[]
|
||||
{
|
||||
new FileEntry { Path = "f", Text = "{{#or}}text{{/or}}" },
|
||||
},
|
||||
Parameters = new[]
|
||||
{
|
||||
new ProjectTemplate.ParameterExpression()
|
||||
{
|
||||
Name = "or",
|
||||
Expression = "dep1||dep2",
|
||||
},
|
||||
},
|
||||
};
|
||||
var generator = new StubbleProjectGeneratorBuilder().WithProjectTemplate(template).Build();
|
||||
|
||||
// Act
|
||||
var project = generator.GenerateProject(spec);
|
||||
|
||||
// Assert
|
||||
project.FileEntries[0].Text.Should().Be("text");
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------- *
|
||||
* negative tests *
|
||||
* ----------------------------------------------------------------- */
|
||||
|
||||
[Fact]
|
||||
public void No_Template_Should_Return_Null_Project()
|
||||
{
|
||||
// Arrange
|
||||
var spec = new ProjectSpec();
|
||||
var generator = new StubbleProjectGeneratorBuilder().Build();
|
||||
|
||||
// Act
|
||||
var project = generator.GenerateProject(spec);
|
||||
|
||||
// Assert
|
||||
project.Should().BeNull();
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------- *
|
||||
* test helpers *
|
||||
* ----------------------------------------------------------------- */
|
||||
|
||||
class StubbleProjectGeneratorBuilder
|
||||
{
|
||||
private Mock<IProjectTemplateRegistry> _registry = new Mock<IProjectTemplateRegistry>();
|
||||
|
||||
private ILogger<StubbleProjectGenerator> _logger = new NullLogger<StubbleProjectGenerator>();
|
||||
|
||||
internal StubbleProjectGenerator Build()
|
||||
{
|
||||
return new StubbleProjectGenerator(_registry.Object, _logger);
|
||||
}
|
||||
|
||||
internal StubbleProjectGeneratorBuilder WithProjectTemplate(ProjectTemplate template)
|
||||
{
|
||||
_registry.Setup(reg => reg.Lookup(It.IsAny<ProjectSpec>())).Returns(template);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using FluentAssertions;
|
||||
using Steeltoe.InitializrApi.Models;
|
||||
using Xunit;
|
||||
|
||||
namespace Steeltoe.InitializrApi.Test.Unit.Models
|
||||
{
|
||||
public class AboutTests
|
||||
{
|
||||
/* ----------------------------------------------------------------- *
|
||||
* positive tests *
|
||||
* ----------------------------------------------------------------- */
|
||||
|
||||
[Fact]
|
||||
public void Properties_Should_Be_Defined()
|
||||
{
|
||||
// Arrange
|
||||
var about = new About();
|
||||
|
||||
// Act
|
||||
|
||||
// Assert
|
||||
about.Name.Should().BeNull();
|
||||
about.Vendor.Should().BeNull();
|
||||
about.Url.Should().BeNull();
|
||||
about.Version.Should().BeNull();
|
||||
about.Commit.Should().BeNull();
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------- *
|
||||
* negative tests *
|
||||
* ----------------------------------------------------------------- */
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using FluentAssertions;
|
||||
using Steeltoe.InitializrApi.Models;
|
||||
using Xunit;
|
||||
|
||||
namespace Steeltoe.InitializrApi.Test.Unit.Models
|
||||
{
|
||||
public class FileEntryTests
|
||||
{
|
||||
/* ----------------------------------------------------------------- *
|
||||
* positive tests *
|
||||
* ----------------------------------------------------------------- */
|
||||
|
||||
[Fact]
|
||||
public void Properties_Should_Be_Defined()
|
||||
{
|
||||
// Arrange
|
||||
var entry = new FileEntry();
|
||||
|
||||
// Act
|
||||
|
||||
// Assert
|
||||
entry.Path.Should().BeNull();
|
||||
entry.Text.Should().BeNull();
|
||||
entry.Rename.Should().BeNull();
|
||||
entry.Dependencies.Should().BeNull();
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------- *
|
||||
* negative tests *
|
||||
* ----------------------------------------------------------------- */
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using FluentAssertions;
|
||||
using Steeltoe.InitializrApi.Models;
|
||||
using Xunit;
|
||||
|
||||
namespace Steeltoe.InitializrApi.Test.Unit.Models
|
||||
{
|
||||
public class InitializrConfigTests
|
||||
{
|
||||
/* ----------------------------------------------------------------- *
|
||||
* positive tests *
|
||||
* ----------------------------------------------------------------- */
|
||||
|
||||
[Fact]
|
||||
public void Properties_Should_Be_Defined()
|
||||
{
|
||||
// Arrange
|
||||
var config = new InitializrConfig();
|
||||
|
||||
// Act
|
||||
|
||||
// Assert
|
||||
config.ProjectMetadata.Should().BeNull();
|
||||
config.ProjectTemplates.Should().BeNull();
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------- *
|
||||
* negative tests *
|
||||
* ----------------------------------------------------------------- */
|
||||
}
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using FluentAssertions;
|
||||
using Steeltoe.InitializrApi.Models;
|
||||
using Xunit;
|
||||
|
||||
namespace Steeltoe.InitializrApi.Test.Unit.Models
|
||||
{
|
||||
public class ProjectMetadataTests
|
||||
{
|
||||
/* ----------------------------------------------------------------- *
|
||||
* positive tests *
|
||||
* ----------------------------------------------------------------- */
|
||||
|
||||
[Fact]
|
||||
public void Properties_Should_Be_Defined()
|
||||
{
|
||||
// Arrange
|
||||
var metadata = new ProjectMetadata();
|
||||
|
||||
// Act
|
||||
|
||||
// Assert
|
||||
metadata.Name.Should().BeNull();
|
||||
metadata.Description.Should().BeNull();
|
||||
metadata.Namespace.Should().BeNull();
|
||||
metadata.SteeltoeVersion.Should().BeNull();
|
||||
metadata.DotNetFramework.Should().BeNull();
|
||||
metadata.DotNetTemplate.Should().BeNull();
|
||||
metadata.Language.Should().BeNull();
|
||||
metadata.ArchiveMimeType.Should().BeNull();
|
||||
metadata.Dependencies.Should().BeNull();
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------- *
|
||||
* negative tests *
|
||||
* ----------------------------------------------------------------- */
|
||||
}
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using FluentAssertions;
|
||||
using Steeltoe.InitializrApi.Models;
|
||||
using Xunit;
|
||||
|
||||
namespace Steeltoe.InitializrApi.Test.Unit.Models
|
||||
{
|
||||
public class ProjectSpecConstraintsTests
|
||||
{
|
||||
/* ----------------------------------------------------------------- *
|
||||
* positive tests *
|
||||
* ----------------------------------------------------------------- */
|
||||
|
||||
[Fact]
|
||||
public void Properties_Should_Be_Defined()
|
||||
{
|
||||
// Arrange
|
||||
var constraints = new ProjectSpecConstraints();
|
||||
|
||||
// Act
|
||||
|
||||
// Assert
|
||||
constraints.SteeltoeVersionRange.Should().BeNull();
|
||||
constraints.DotNetFrameworkRange.Should().BeNull();
|
||||
constraints.DotNetTemplate.Should().BeNull();
|
||||
constraints.Language.Should().BeNull();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ToString_Should_Be_User_Friendly()
|
||||
{
|
||||
// Arrange
|
||||
var constraints = new ProjectSpecConstraints();
|
||||
|
||||
// Act
|
||||
var s = constraints.ToString();
|
||||
|
||||
// Assert
|
||||
s.Should().Be("[steeltoeVersionRange=,dotNetFrameworkRange=,dotNetTemplate=,language=]");
|
||||
|
||||
// Arrange
|
||||
constraints.SteeltoeVersionRange = "myversion";
|
||||
|
||||
// Act
|
||||
s = constraints.ToString();
|
||||
|
||||
// Assert
|
||||
s.Should().Be("[steeltoeVersionRange=myversion,dotNetFrameworkRange=,dotNetTemplate=,language=]");
|
||||
|
||||
// Arrange
|
||||
constraints.DotNetFrameworkRange = "myframework";
|
||||
|
||||
// Act
|
||||
s = constraints.ToString();
|
||||
|
||||
// Assert
|
||||
s.Should().Be("[steeltoeVersionRange=myversion,dotNetFrameworkRange=myframework,dotNetTemplate=,language=]");
|
||||
|
||||
// Arrange
|
||||
constraints.DotNetTemplate = "mytemplate";
|
||||
|
||||
// Act
|
||||
s = constraints.ToString();
|
||||
|
||||
// Assert
|
||||
s.Should().Be("[steeltoeVersionRange=myversion,dotNetFrameworkRange=myframework,dotNetTemplate=mytemplate,language=]");
|
||||
|
||||
// Arrange
|
||||
constraints.Language = "mylanguage";
|
||||
|
||||
// Act
|
||||
s = constraints.ToString();
|
||||
|
||||
// Assert
|
||||
s.Should().Be("[steeltoeVersionRange=myversion,dotNetFrameworkRange=myframework,dotNetTemplate=mytemplate,language=mylanguage]");
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------- *
|
||||
* negative tests *
|
||||
* ----------------------------------------------------------------- */
|
||||
}
|
||||
}
|
|
@ -0,0 +1,142 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using FluentAssertions;
|
||||
using Steeltoe.InitializrApi.Models;
|
||||
using Xunit;
|
||||
|
||||
namespace Steeltoe.InitializrApi.Test.Unit.Models
|
||||
{
|
||||
public class ProjectSpecTests
|
||||
{
|
||||
/* ----------------------------------------------------------------- *
|
||||
* positive tests *
|
||||
* ----------------------------------------------------------------- */
|
||||
|
||||
[Fact]
|
||||
public void Properties_Should_Be_Defined()
|
||||
{
|
||||
// Arrange
|
||||
var spec = new ProjectSpec();
|
||||
|
||||
// Act
|
||||
|
||||
// Assert
|
||||
spec.Name.Should().BeNull();
|
||||
spec.Description.Should().BeNull();
|
||||
spec.Namespace.Should().BeNull();
|
||||
spec.SteeltoeVersion.Should().BeNull();
|
||||
spec.DotNetFramework.Should().BeNull();
|
||||
spec.DotNetTemplate.Should().BeNull();
|
||||
spec.Language.Should().BeNull();
|
||||
spec.ArchiveMimeType.Should().BeNull();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Application_Should_Be_Assumed()
|
||||
{
|
||||
// Arrange
|
||||
var spec = new ProjectSpec { ArchiveMimeType = "foo" };
|
||||
|
||||
// Act
|
||||
|
||||
// Assert
|
||||
spec.ArchiveMimeType.Should().Be("application/foo");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ToString_Should_Be_User_Friendly()
|
||||
{
|
||||
// Arrange
|
||||
var spec = new ProjectSpec();
|
||||
|
||||
// Act
|
||||
var s = spec.ToString();
|
||||
|
||||
// Assert
|
||||
s.Should().Be("[]");
|
||||
|
||||
// Arrange
|
||||
spec.ArchiveMimeType = "mymimetype";
|
||||
|
||||
// Act
|
||||
s = spec.ToString();
|
||||
|
||||
// Assert
|
||||
s.Should().Be("[archiveMimeType=application/mymimetype]");
|
||||
|
||||
// Arrange
|
||||
spec.Language = "mylanguage";
|
||||
|
||||
// Act
|
||||
s = spec.ToString();
|
||||
|
||||
// Assert
|
||||
s.Should().Be("[language=mylanguage,archiveMimeType=application/mymimetype]");
|
||||
|
||||
// Arrange
|
||||
spec.DotNetTemplate = "mytemplate";
|
||||
|
||||
// Act
|
||||
s = spec.ToString();
|
||||
|
||||
// Assert
|
||||
s.Should().Be("[dotNetTemplate=mytemplate,language=mylanguage,archiveMimeType=application/mymimetype]");
|
||||
|
||||
// Arrange
|
||||
spec.DotNetFramework = "myframework";
|
||||
|
||||
// Act
|
||||
s = spec.ToString();
|
||||
|
||||
// Assert
|
||||
s.Should().Be(
|
||||
"[dotNetFramework=myframework,dotNetTemplate=mytemplate,language=mylanguage,archiveMimeType=application/mymimetype]");
|
||||
|
||||
// Arrange
|
||||
spec.SteeltoeVersion = "mysteeltoeversion";
|
||||
|
||||
// Act
|
||||
s = spec.ToString();
|
||||
|
||||
// Assert
|
||||
s.Should().Be(
|
||||
"[steeltoeVersion=mysteeltoeversion,dotNetFramework=myframework,dotNetTemplate=mytemplate,language=mylanguage,archiveMimeType=application/mymimetype]");
|
||||
|
||||
// Arrange
|
||||
spec.Namespace = "mynamespace";
|
||||
|
||||
// Act
|
||||
s = spec.ToString();
|
||||
|
||||
// Assert
|
||||
s.Should().Be(
|
||||
"[namespace=mynamespace,steeltoeVersion=mysteeltoeversion,dotNetFramework=myframework,dotNetTemplate=mytemplate,language=mylanguage,archiveMimeType=application/mymimetype]");
|
||||
|
||||
// Arrange
|
||||
spec.Description = "mydesc";
|
||||
|
||||
// Act
|
||||
s = spec.ToString();
|
||||
|
||||
// Assert
|
||||
s.Should().Be(
|
||||
"[description=mydesc,namespace=mynamespace,steeltoeVersion=mysteeltoeversion,dotNetFramework=myframework,dotNetTemplate=mytemplate,language=mylanguage,archiveMimeType=application/mymimetype]");
|
||||
|
||||
// Arrange
|
||||
spec.Name = "myname";
|
||||
|
||||
// Act
|
||||
s = spec.ToString();
|
||||
|
||||
// Assert
|
||||
s.Should().Be(
|
||||
"[name=myname,description=mydesc,namespace=mynamespace,steeltoeVersion=mysteeltoeversion,dotNetFramework=myframework,dotNetTemplate=mytemplate,language=mylanguage,archiveMimeType=application/mymimetype]");
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------- *
|
||||
* negative tests *
|
||||
* ----------------------------------------------------------------- */
|
||||
}
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using FluentAssertions;
|
||||
using Steeltoe.InitializrApi.Models;
|
||||
using Xunit;
|
||||
|
||||
namespace Steeltoe.InitializrApi.Test.Unit.Models
|
||||
{
|
||||
public class ProjectTemplateConfigurationTests
|
||||
{
|
||||
/* ----------------------------------------------------------------- *
|
||||
* positive tests *
|
||||
* ----------------------------------------------------------------- */
|
||||
|
||||
[Fact]
|
||||
public void Properties_Should_Be_Defined()
|
||||
{
|
||||
// Arrange
|
||||
var config = new ProjectTemplateConfiguration();
|
||||
|
||||
// Act
|
||||
|
||||
// Assert
|
||||
config.Uri.Should().BeNull();
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------- *
|
||||
* negative tests *
|
||||
* ----------------------------------------------------------------- */
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using FluentAssertions;
|
||||
using Steeltoe.InitializrApi.Models;
|
||||
using Xunit;
|
||||
|
||||
namespace Steeltoe.InitializrApi.Test.Unit.Models
|
||||
{
|
||||
public class ProjectTemplateTests
|
||||
{
|
||||
/* ----------------------------------------------------------------- *
|
||||
* positive tests *
|
||||
* ----------------------------------------------------------------- */
|
||||
|
||||
[Fact]
|
||||
public void Properties_Should_Be_Defined()
|
||||
{
|
||||
// Arrange
|
||||
var template = new ProjectTemplate();
|
||||
|
||||
// Act
|
||||
|
||||
// Assert
|
||||
template.Description.Should().BeNull();
|
||||
template.Constraints.Should().BeNull();
|
||||
template.Manifest.Should().BeNull();
|
||||
template.Parameters.Should().BeNull();
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------- *
|
||||
* negative tests *
|
||||
* ----------------------------------------------------------------- */
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using FluentAssertions;
|
||||
using Steeltoe.InitializrApi.Models;
|
||||
using Xunit;
|
||||
|
||||
namespace Steeltoe.InitializrApi.Test.Unit.Models
|
||||
{
|
||||
public class ProjectTests
|
||||
{
|
||||
/* ----------------------------------------------------------------- *
|
||||
* positive tests *
|
||||
* ----------------------------------------------------------------- */
|
||||
|
||||
[Fact]
|
||||
public void Properties_Should_Be_Defined()
|
||||
{
|
||||
// Arrange
|
||||
var project = new Project();
|
||||
|
||||
// Act
|
||||
|
||||
// Assert
|
||||
project.Spec.Should().BeNull();
|
||||
project.FileEntries.Should().NotBeNull();
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------- *
|
||||
* negative tests *
|
||||
* ----------------------------------------------------------------- */
|
||||
}
|
||||
}
|
|
@ -0,0 +1,18 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="..\Directory.Build.props">
|
||||
<Link>Directory.Build.props</Link>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\InitializrApi\Steeltoe.InitializrApi.csproj" />
|
||||
<ProjectReference Include="..\InitializrApi.Test.Utils\Steeltoe.InitializrApi.Test.Utils.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="YamlDotNet" Version="8.1.2" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
|
@ -0,0 +1,464 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using FluentAssertions;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using Moq;
|
||||
using Steeltoe.InitializrApi.Models;
|
||||
using Steeltoe.InitializrApi.Services;
|
||||
using Steeltoe.InitializrApi.Templates;
|
||||
using Steeltoe.InitializrApi.Test.Utils;
|
||||
using Xunit;
|
||||
|
||||
namespace Steeltoe.InitializrApi.Test.Unit.Templates
|
||||
{
|
||||
public class ProjectTemplateRegistryTests
|
||||
{
|
||||
/* ----------------------------------------------------------------- *
|
||||
* positive tests *
|
||||
* ----------------------------------------------------------------- */
|
||||
|
||||
[Fact]
|
||||
public void Files_In_Project_Template_Should_Match_Manifest()
|
||||
{
|
||||
// Arrange
|
||||
var config = new InitializrConfig
|
||||
{
|
||||
ProjectTemplates = new[]
|
||||
{
|
||||
new ProjectTemplateConfiguration
|
||||
{
|
||||
Uri = new Uri("pt:///izr"),
|
||||
},
|
||||
},
|
||||
};
|
||||
var registry = new TemplateRegistryBuilder().WithConfig(config).Build();
|
||||
|
||||
// Act
|
||||
var template = registry.Lookup(new ProjectSpec());
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(template);
|
||||
var fileEntries = template.Manifest.ToList();
|
||||
fileEntries.Count().Should().Be(3);
|
||||
fileEntries[0].Path.Should().Be("f1");
|
||||
fileEntries[0].Text.Should().Be("my file f1");
|
||||
fileEntries[0].Rename.Should().BeNull();
|
||||
fileEntries[1].Path.Should().Be("d1/");
|
||||
fileEntries[1].Text.Should().BeNull();
|
||||
fileEntries[1].Rename.Should().BeNull();
|
||||
fileEntries[2].Path.Should().Be("r1");
|
||||
fileEntries[2].Text.Should().Be("my file r1->n1");
|
||||
fileEntries[2].Rename.Should().Be("n1");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Lookup_Should_Find_Match()
|
||||
{
|
||||
// Arrange
|
||||
var config = new InitializrConfig
|
||||
{
|
||||
ProjectTemplates = new[]
|
||||
{
|
||||
new ProjectTemplateConfiguration
|
||||
{
|
||||
Uri = new Uri(
|
||||
"pt:///izr?description=pt1&steeltoeVersionRange=st1&dotNetFrameworkRange=df1&dotNetTemplate=dt1&language=l1"),
|
||||
},
|
||||
new ProjectTemplateConfiguration
|
||||
{
|
||||
Uri = new Uri(
|
||||
"pt:///izr?description=pt2&steeltoeVersionRange=st2&dotNetFrameworkRange=df1&dotNetTemplate=dt1&language=l1"),
|
||||
},
|
||||
new ProjectTemplateConfiguration
|
||||
{
|
||||
Uri = new Uri(
|
||||
"pt:///izr?description=pt3&steeltoeVersionRange=st2&dotNetFrameworkRange=df2&dotNetTemplate=dt1&language=l1"),
|
||||
},
|
||||
new ProjectTemplateConfiguration
|
||||
{
|
||||
Uri = new Uri(
|
||||
"pt:///izr?description=pt4&steeltoeVersionRange=st2&dotNetFrameworkRange=df2&dotNetTemplate=dt2&language=l1"),
|
||||
},
|
||||
new ProjectTemplateConfiguration
|
||||
{
|
||||
Uri = new Uri(
|
||||
"pt:///izr?description=pt5&steeltoeVersionRange=st2&dotNetFrameworkRange=df2&dotNetTemplate=dt2&language=l2"),
|
||||
},
|
||||
},
|
||||
};
|
||||
var registry = new TemplateRegistryBuilder().WithConfig(config).Build();
|
||||
|
||||
// Act
|
||||
var template = registry.Lookup(new ProjectSpec
|
||||
{ SteeltoeVersion = "st1", DotNetFramework = "df1", DotNetTemplate = "dt1", Language = "l1" });
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(template);
|
||||
template.Description.Should().Be("pt1");
|
||||
|
||||
// Act
|
||||
template = registry.Lookup(new ProjectSpec
|
||||
{ SteeltoeVersion = "st2", DotNetFramework = "df1", DotNetTemplate = "dt1", Language = "l1" });
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(template);
|
||||
template.Description.Should().Be("pt2");
|
||||
|
||||
// Act
|
||||
template = registry.Lookup(new ProjectSpec
|
||||
{ SteeltoeVersion = "st2", DotNetFramework = "df2", DotNetTemplate = "dt1", Language = "l1" });
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(template);
|
||||
template.Description.Should().Be("pt3");
|
||||
|
||||
// Act
|
||||
template = registry.Lookup(new ProjectSpec
|
||||
{ SteeltoeVersion = "st2", DotNetFramework = "df2", DotNetTemplate = "dt2", Language = "l1" });
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(template);
|
||||
template.Description.Should().Be("pt4");
|
||||
|
||||
// Act
|
||||
template = registry.Lookup(new ProjectSpec
|
||||
{ SteeltoeVersion = "st2", DotNetFramework = "df2", DotNetTemplate = "dt2", Language = "l2" });
|
||||
|
||||
// Assert
|
||||
Assert.NotNull(template);
|
||||
template.Description.Should().Be("pt5");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Initialize_Should_Reset_State()
|
||||
{
|
||||
// Arrange
|
||||
var config = new InitializrConfig
|
||||
{
|
||||
ProjectTemplates = new[]
|
||||
{
|
||||
new ProjectTemplateConfiguration
|
||||
{
|
||||
Uri = new Uri("pt:///izr"),
|
||||
},
|
||||
},
|
||||
};
|
||||
var registry = new TemplateRegistryBuilder().WithConfig(config).Build();
|
||||
|
||||
// Act
|
||||
var template = registry.Lookup(new ProjectSpec());
|
||||
|
||||
// Assert
|
||||
template.Should().NotBeNull();
|
||||
|
||||
// Arrange
|
||||
config.ProjectTemplates = new ProjectTemplateConfiguration[0];
|
||||
|
||||
// Act
|
||||
registry.Initialize();
|
||||
template = registry.Lookup(new ProjectSpec());
|
||||
|
||||
// Assert
|
||||
template.Should().BeNull();
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------- *
|
||||
* negative tests *
|
||||
* ----------------------------------------------------------------- */
|
||||
|
||||
[Fact]
|
||||
public void Project_Templates_Not_Configured_Should_Log_An_Error()
|
||||
{
|
||||
// Arrange
|
||||
var config = new InitializrConfig();
|
||||
var logger = new Mock<ILogger<ProjectTemplateRegistry>>();
|
||||
|
||||
// Act
|
||||
new TemplateRegistryBuilder().WithConfig(config).WithLogger(logger.Object).Build();
|
||||
|
||||
// Assert
|
||||
logger.VerifyLog(LogLevel.Error, "Templates not configured.");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Uri_File_Not_Found_Should_Log_An_Error()
|
||||
{
|
||||
// Arrange
|
||||
var config = new InitializrConfig
|
||||
{
|
||||
ProjectTemplates = new[]
|
||||
{
|
||||
new ProjectTemplateConfiguration
|
||||
{
|
||||
Uri = new Uri("pt:///no/such/file"),
|
||||
}
|
||||
},
|
||||
};
|
||||
var logger = new Mock<ILogger<ProjectTemplateRegistry>>();
|
||||
|
||||
// Act
|
||||
new TemplateRegistryBuilder().WithConfig(config).WithLogger(logger.Object).Build();
|
||||
|
||||
// Assert
|
||||
logger.VerifyLog(LogLevel.Error, "URI not found: pt:///no/such/file");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Uri_Directory_Not_Found_Should_Log_An_Error()
|
||||
{
|
||||
// Arrange
|
||||
var config = new InitializrConfig
|
||||
{
|
||||
ProjectTemplates = new[]
|
||||
{
|
||||
new ProjectTemplateConfiguration
|
||||
{
|
||||
Uri = new Uri("pt:///no/such/dir/"),
|
||||
}
|
||||
},
|
||||
};
|
||||
var logger = new Mock<ILogger<ProjectTemplateRegistry>>();
|
||||
|
||||
// Act
|
||||
new TemplateRegistryBuilder().WithConfig(config).WithLogger(logger.Object).Build();
|
||||
|
||||
// Assert
|
||||
logger.VerifyLog(LogLevel.Error, "URI not found: pt:///no/such/dir/");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Uri_Null_Stream_Should_Log_An_Error()
|
||||
{
|
||||
// Arrange
|
||||
var config = new InitializrConfig
|
||||
{
|
||||
ProjectTemplates = new[]
|
||||
{
|
||||
new ProjectTemplateConfiguration
|
||||
{
|
||||
Uri = new Uri("pt:///stream/null"),
|
||||
}
|
||||
},
|
||||
};
|
||||
var logger = new Mock<ILogger<ProjectTemplateRegistry>>();
|
||||
|
||||
// Act
|
||||
new TemplateRegistryBuilder().WithConfig(config).WithLogger(logger.Object).Build();
|
||||
|
||||
// Assert
|
||||
logger.VerifyLog(LogLevel.Error, "URI returned null stream: pt:///stream/null");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Uri_Non_Zip_Stream_Should_Log_An_Error()
|
||||
{
|
||||
// Arrange
|
||||
var config = new InitializrConfig
|
||||
{
|
||||
ProjectTemplates = new[]
|
||||
{
|
||||
new ProjectTemplateConfiguration
|
||||
{
|
||||
Uri = new Uri("pt:///stream/empty"),
|
||||
}
|
||||
},
|
||||
};
|
||||
var configService = new Mock<IInitializrConfigService>();
|
||||
configService.Setup(svc => svc.GetInitializrConfig()).Returns(config);
|
||||
var logger = new Mock<ILogger<ProjectTemplateRegistry>>();
|
||||
|
||||
// Act
|
||||
new TemplateRegistryBuilder().WithConfig(config).WithLogger(logger.Object).Build();
|
||||
|
||||
// Assert
|
||||
logger.VerifyLog(LogLevel.Error, "URI not a Zip archive: pt:///stream/empty");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Uri_Unexpected_Error_Should_Log_An_Error()
|
||||
{
|
||||
// Arrange
|
||||
var config = new InitializrConfig
|
||||
{
|
||||
ProjectTemplates = new[]
|
||||
{
|
||||
new ProjectTemplateConfiguration
|
||||
{
|
||||
Uri = new Uri("pt:///error"),
|
||||
}
|
||||
},
|
||||
};
|
||||
var logger = new Mock<ILogger<ProjectTemplateRegistry>>();
|
||||
|
||||
// Act
|
||||
new TemplateRegistryBuilder().WithConfig(config).WithLogger(logger.Object).Build();
|
||||
|
||||
// Assert
|
||||
logger.VerifyLog(LogLevel.Error, "Unexpected error [System.Exception[some error message]]: pt:///error");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Missing_Metadata_Should_Log_An_Error()
|
||||
{
|
||||
// Arrange
|
||||
var config = new InitializrConfig
|
||||
{
|
||||
ProjectTemplates = new[]
|
||||
{
|
||||
new ProjectTemplateConfiguration
|
||||
{
|
||||
Uri = new Uri("pt:///izr?metadata=no"),
|
||||
}
|
||||
},
|
||||
};
|
||||
var logger = new Mock<ILogger<ProjectTemplateRegistry>>();
|
||||
|
||||
// Act
|
||||
new TemplateRegistryBuilder().WithConfig(config).WithLogger(logger.Object).Build();
|
||||
|
||||
// Assert
|
||||
logger.VerifyLog(LogLevel.Error,
|
||||
"Project template metadata missing ('.IZR/metadata.yaml'): pt:///izr?metadata=no");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Malformed_Metadata_Should_Log_An_Error()
|
||||
{
|
||||
// Arrange
|
||||
var config = new InitializrConfig
|
||||
{
|
||||
ProjectTemplates = new[]
|
||||
{
|
||||
new ProjectTemplateConfiguration
|
||||
{
|
||||
Uri = new Uri("pt:///izr?metadata=malformed"),
|
||||
}
|
||||
},
|
||||
};
|
||||
var logger = new Mock<ILogger<ProjectTemplateRegistry>>();
|
||||
|
||||
// Act
|
||||
new TemplateRegistryBuilder().WithConfig(config).WithLogger(logger.Object).Build();
|
||||
|
||||
// Assert
|
||||
logger.VerifyLog(LogLevel.Error,
|
||||
"Project template metadata malformed ('.IZR/metadata.yaml'): pt:///izr?metadata=malformed");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Missing_Constraints_Should_Log_An_Error()
|
||||
{
|
||||
// Arrange
|
||||
var config = new InitializrConfig
|
||||
{
|
||||
ProjectTemplates = new[]
|
||||
{
|
||||
new ProjectTemplateConfiguration
|
||||
{
|
||||
Uri = new Uri("pt:///izr?constraints=no"),
|
||||
}
|
||||
},
|
||||
};
|
||||
var logger = new Mock<ILogger<ProjectTemplateRegistry>>();
|
||||
|
||||
// Act
|
||||
new TemplateRegistryBuilder().WithConfig(config).WithLogger(logger.Object).Build();
|
||||
|
||||
// Assert
|
||||
logger.VerifyLog(LogLevel.Error, "Project template constraints missing: pt:///izr?constraints=no");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Missing_Manifest_Should_Log_An_Error()
|
||||
{
|
||||
// Arrange
|
||||
var config = new InitializrConfig
|
||||
{
|
||||
ProjectTemplates = new[]
|
||||
{
|
||||
new ProjectTemplateConfiguration
|
||||
{
|
||||
Uri = new Uri("pt:///izr?manifest=no"),
|
||||
}
|
||||
},
|
||||
};
|
||||
var logger = new Mock<ILogger<ProjectTemplateRegistry>>();
|
||||
|
||||
// Act
|
||||
new TemplateRegistryBuilder().WithConfig(config).WithLogger(logger.Object).Build();
|
||||
|
||||
// Assert
|
||||
logger.VerifyLog(LogLevel.Error, "Project template manifest missing: pt:///izr?manifest=no");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Missing_File_Should_Log_An_Error()
|
||||
{
|
||||
// Arrange
|
||||
var config = new InitializrConfig
|
||||
{
|
||||
ProjectTemplates = new[]
|
||||
{
|
||||
new ProjectTemplateConfiguration
|
||||
{
|
||||
Uri = new Uri("pt:///izr?missingfile=yes"),
|
||||
}
|
||||
},
|
||||
};
|
||||
var logger = new Mock<ILogger<ProjectTemplateRegistry>>();
|
||||
|
||||
// Act
|
||||
new TemplateRegistryBuilder().WithConfig(config).WithLogger(logger.Object).Build();
|
||||
|
||||
// Assert
|
||||
logger.VerifyLog(LogLevel.Error, "Project template missing file: 'f1' pt:///izr?missingfile=yes");
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------- *
|
||||
* test helpers *
|
||||
* ----------------------------------------------------------------- */
|
||||
|
||||
static ProjectTemplateRegistryTests()
|
||||
{
|
||||
WebRequest.RegisterPrefix("pt", new MockProjectTemplateWebScheme());
|
||||
}
|
||||
|
||||
class TemplateRegistryBuilder
|
||||
{
|
||||
private InitializrConfig _config = new InitializrConfig
|
||||
{
|
||||
ProjectMetadata = new ProjectMetadata(),
|
||||
ProjectTemplates = new ProjectTemplateConfiguration[0],
|
||||
};
|
||||
|
||||
private ILogger<ProjectTemplateRegistry> _logger = new NullLogger<ProjectTemplateRegistry>();
|
||||
|
||||
internal ProjectTemplateRegistry Build()
|
||||
{
|
||||
var configService = new Mock<IInitializrConfigService>();
|
||||
configService.Setup(svc => svc.GetInitializrConfig()).Returns(_config);
|
||||
var registry = new ProjectTemplateRegistry(configService.Object, _logger);
|
||||
registry.Initialize();
|
||||
return registry;
|
||||
}
|
||||
|
||||
internal TemplateRegistryBuilder WithConfig(InitializrConfig config)
|
||||
{
|
||||
_config = config;
|
||||
return this;
|
||||
}
|
||||
|
||||
internal TemplateRegistryBuilder WithLogger(ILogger<ProjectTemplateRegistry> logger)
|
||||
{
|
||||
_logger = logger;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
// Borrowed from https://gist.github.com/changhuixu/c59b18ad7523562eabfa2016546d3b26
|
||||
|
||||
using System;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Moq;
|
||||
|
||||
namespace Steeltoe.InitializrApi.Test.Utils
|
||||
{
|
||||
public static class MockLoggerExtensions
|
||||
{
|
||||
public static void VerifyLog<T>(this Mock<ILogger<T>> loggerMock, LogLevel level, string message,
|
||||
string failMessage = null)
|
||||
{
|
||||
loggerMock.VerifyLog(level, message, Times.Once(), failMessage);
|
||||
}
|
||||
|
||||
public static void VerifyLog<T>(this Mock<ILogger<T>> loggerMock, LogLevel level, string message, Times times,
|
||||
string failMessage = null)
|
||||
{
|
||||
loggerMock.Verify(l => l.Log(level, It.IsAny<EventId>(),
|
||||
It.Is<It.IsAnyType>((o, _) => o.ToString() == message), It.IsAny<Exception>(),
|
||||
It.Is<Func<It.IsAnyType, Exception, string>>((v, t) => true)),
|
||||
times, failMessage);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Net;
|
||||
|
||||
namespace Steeltoe.InitializrApi.Test.Utils
|
||||
{
|
||||
public class MockProjectTemplateWebRequest : WebRequest
|
||||
{
|
||||
private Uri _uri;
|
||||
|
||||
public MockProjectTemplateWebRequest(Uri uri)
|
||||
{
|
||||
_uri = uri;
|
||||
}
|
||||
|
||||
public override WebResponse GetResponse()
|
||||
{
|
||||
return new MockProjectTemplateWebResponse(_uri);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,160 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Net;
|
||||
using System.Text;
|
||||
|
||||
namespace Steeltoe.InitializrApi.Test.Utils
|
||||
{
|
||||
public class MockProjectTemplateWebResponse : WebResponse
|
||||
{
|
||||
private Uri _uri;
|
||||
|
||||
public MockProjectTemplateWebResponse(Uri uri)
|
||||
{
|
||||
_uri = uri;
|
||||
}
|
||||
|
||||
public override Stream GetResponseStream()
|
||||
{
|
||||
switch (_uri.AbsolutePath)
|
||||
{
|
||||
case "/error":
|
||||
return Error();
|
||||
case "/izr":
|
||||
return IzrSteam();
|
||||
case "/no/such/file":
|
||||
return NoSuchFile();
|
||||
case "/no/such/dir/":
|
||||
return NoSuchDirectory();
|
||||
case "/stream/empty":
|
||||
return EmptyStream();
|
||||
case "/stream/null":
|
||||
return NullSteam();
|
||||
case "/zip":
|
||||
return ZipSteam();
|
||||
default:
|
||||
throw new UriFormatException($"Don't know how to create test stream: {_uri}");
|
||||
}
|
||||
}
|
||||
|
||||
private Stream IzrSteam()
|
||||
{
|
||||
var buf = new MemoryStream();
|
||||
var archive = new ZipArchive(buf, ZipArchiveMode.Create, true);
|
||||
|
||||
var queryParams = new Dictionary<string, string>()
|
||||
{
|
||||
{ "constraints", "yes" },
|
||||
{ "description", "project template description" },
|
||||
{ "dotNetFrameworkRange", "" },
|
||||
{ "dotNetTemplate", "" },
|
||||
{ "language", "" },
|
||||
{ "manifest", "yes" },
|
||||
{ "metadata", "yes" },
|
||||
{ "missingfile", "" },
|
||||
{ "steeltoeVersionRange", "" },
|
||||
};
|
||||
if (_uri.Query.StartsWith('?'))
|
||||
{
|
||||
foreach (var nameValuePair in _uri.Query.Substring(1).Split('&'))
|
||||
{
|
||||
var queryParam = nameValuePair.Split('=', 2);
|
||||
queryParams[queryParam[0]] = queryParam[1];
|
||||
}
|
||||
}
|
||||
|
||||
if (!queryParams["metadata"].Equals("no"))
|
||||
{
|
||||
var metadata = new StringBuilder();
|
||||
if (queryParams["metadata"].Equals("malformed"))
|
||||
{
|
||||
metadata.Append("malformed yaml");
|
||||
}
|
||||
else
|
||||
{
|
||||
metadata.Append("description: ").Append(queryParams["description"]).Append(Environment.NewLine);
|
||||
if (!queryParams["constraints"].Equals("no"))
|
||||
{
|
||||
metadata.Append("constraints:").Append(Environment.NewLine);
|
||||
metadata.Append($" steeltoeVersionRange: {queryParams["steeltoeVersionRange"]}")
|
||||
.Append(Environment.NewLine);
|
||||
metadata.Append($" dotNetFrameworkRange: {queryParams["dotNetFrameworkRange"]}")
|
||||
.Append(Environment.NewLine);
|
||||
metadata.Append($" dotNetTemplate: {queryParams["dotNetTemplate"]}")
|
||||
.Append(Environment.NewLine);
|
||||
metadata.Append($" language: {queryParams["language"]}").Append(Environment.NewLine);
|
||||
}
|
||||
|
||||
// manifest
|
||||
if (!queryParams["manifest"].Equals("no"))
|
||||
{
|
||||
metadata.Append("manifest:").Append(Environment.NewLine);
|
||||
metadata.Append("- path: f1").Append(Environment.NewLine);
|
||||
metadata.Append("- path: d1/").Append(Environment.NewLine);
|
||||
metadata.Append("- path: r1").Append(Environment.NewLine);
|
||||
metadata.Append(" rename: n1").Append(Environment.NewLine);
|
||||
}
|
||||
}
|
||||
|
||||
WriteEntryText(archive.CreateEntry(".IZR/metadata.yaml"), metadata.ToString());
|
||||
}
|
||||
|
||||
if (!queryParams["missingfile"].Equals("yes"))
|
||||
{
|
||||
WriteEntryText(archive.CreateEntry("f1"), "my file f1");
|
||||
}
|
||||
|
||||
archive.CreateEntry("d1/");
|
||||
WriteEntryText(archive.CreateEntry("r1"), "my file r1->n1");
|
||||
|
||||
archive.Dispose();
|
||||
return buf;
|
||||
}
|
||||
|
||||
private static void WriteEntryText(ZipArchiveEntry entry, string text)
|
||||
{
|
||||
using var stream = entry.Open();
|
||||
using var writer = new StreamWriter(stream);
|
||||
writer.Write(text);
|
||||
}
|
||||
|
||||
private Stream ZipSteam()
|
||||
{
|
||||
var buf = new MemoryStream();
|
||||
var archive = new ZipArchive(buf, ZipArchiveMode.Create, true);
|
||||
archive.Dispose();
|
||||
return buf;
|
||||
}
|
||||
|
||||
private Stream EmptyStream()
|
||||
{
|
||||
return new MemoryStream();
|
||||
}
|
||||
|
||||
private Stream NullSteam()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
private Stream NoSuchFile()
|
||||
{
|
||||
throw new WebException("URI not found", new FileNotFoundException(_uri.ToString()));
|
||||
}
|
||||
|
||||
private Stream NoSuchDirectory()
|
||||
{
|
||||
throw new WebException("URI not found", new DirectoryNotFoundException(_uri.ToString()));
|
||||
}
|
||||
|
||||
private Stream Error()
|
||||
{
|
||||
throw new Exception($"some error message");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Net;
|
||||
|
||||
namespace Steeltoe.InitializrApi.Test.Utils
|
||||
{
|
||||
public class MockProjectTemplateWebScheme : IWebRequestCreate
|
||||
{
|
||||
public WebRequest Create(Uri uri)
|
||||
{
|
||||
return new MockProjectTemplateWebRequest(uri);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
using System.Text.Json;
|
||||
|
||||
namespace Steeltoe.InitializrApi.Test.Utils
|
||||
{
|
||||
public static class Serializer
|
||||
{
|
||||
private static JsonSerializerOptions Options { get; } = new JsonSerializerOptions
|
||||
{
|
||||
PropertyNameCaseInsensitive = true,
|
||||
};
|
||||
|
||||
public static T DeserializeJson<T>(string json)
|
||||
{
|
||||
return JsonSerializer.Deserialize<T>(json, Options);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using FluentAssertions;
|
||||
using Xunit;
|
||||
|
||||
namespace Steeltoe.InitializrApi.Test.Utils
|
||||
{
|
||||
public class SerializerTest
|
||||
{
|
||||
/* ----------------------------------------------------------------- *
|
||||
* positive tests *
|
||||
* ----------------------------------------------------------------- */
|
||||
|
||||
[Fact]
|
||||
public void DeserializeJson_Should_Return_Deserialized_Object()
|
||||
{
|
||||
// Arrange
|
||||
var json = @"{""DummyProperty"": ""dummy""}";
|
||||
|
||||
// Act
|
||||
var dummy = Serializer.DeserializeJson<DummyObject>(json);
|
||||
|
||||
// Assert
|
||||
dummy.Should().NotBeNull();
|
||||
dummy.DummyProperty.Should().Be("dummy");
|
||||
}
|
||||
|
||||
/* ----------------------------------------------------------------- *
|
||||
* negative tests *
|
||||
* ----------------------------------------------------------------- */
|
||||
|
||||
/* ----------------------------------------------------------------- *
|
||||
* test helpers *
|
||||
* ----------------------------------------------------------------- */
|
||||
|
||||
public class DummyObject
|
||||
{
|
||||
public string DummyProperty { get; set; }
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="..\Directory.Build.props">
|
||||
<Link>Directory.Build.props</Link>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="YamlDotNet" Version="8.1.2" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
|
@ -5,7 +5,7 @@
|
|||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace Steeltoe.InitializrApi.Test.TestUtils
|
||||
namespace Steeltoe.InitializrApi.Test.Utils
|
||||
{
|
||||
public sealed class TempFile : IDisposable
|
||||
{
|
|
@ -1,38 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Threading.Tasks;
|
||||
using FluentAssertions;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Moq;
|
||||
using Steeltoe.Extensions.Configuration.ConfigServer;
|
||||
using Steeltoe.InitializrApi.Configuration;
|
||||
using Steeltoe.InitializrApi.Models;
|
||||
using Xunit;
|
||||
|
||||
namespace Steeltoe.InitializrApi.Test.Configuration
|
||||
{
|
||||
public class ConfigServerConfigurationRepositoryTest
|
||||
{
|
||||
[Fact]
|
||||
public async Task ConfigurationShouldNotBeNull()
|
||||
{
|
||||
// Arrange
|
||||
var expected = new InitializrApiConfiguration();
|
||||
var mockConfigOptions = new Mock<IOptions<InitializrApiConfiguration>>();
|
||||
mockConfigOptions.Setup(opts => opts.Value).Returns(expected);
|
||||
var mockSettings = new ConfigServerClientSettingsOptions {Uri = "a uri"};
|
||||
var mockSettingsOptions = new Mock<IOptions<ConfigServerClientSettingsOptions>>();
|
||||
mockSettingsOptions.Setup(settings => settings.Value).Returns(mockSettings);
|
||||
var repo = new ConfigServerConfigurationRepository(mockConfigOptions.Object);
|
||||
|
||||
// Act
|
||||
var actual = await repo.GetConfiguration();
|
||||
|
||||
// Assert
|
||||
Assert.IsType<InitializrApiConfiguration>(actual);
|
||||
actual.Should().Be(expected);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,92 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using FluentAssertions;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Moq;
|
||||
using Steeltoe.InitializrApi.Controllers;
|
||||
using Steeltoe.InitializrApi.Models;
|
||||
using Steeltoe.InitializrApi.Services;
|
||||
using Steeltoe.InitializrApi.Test.TestUtils;
|
||||
using Xunit;
|
||||
|
||||
namespace Steeltoe.InitializrApi.Test.Controllers
|
||||
{
|
||||
public class AboutControllerTest
|
||||
{
|
||||
private const string Endpoint = "/api/about";
|
||||
|
||||
[Fact]
|
||||
public void GetAbout()
|
||||
{
|
||||
// Arrange
|
||||
var controller = new AboutController();
|
||||
|
||||
// Act
|
||||
var result = controller.GetAbout();
|
||||
|
||||
// Assert
|
||||
var indexResult = Assert.IsType<OkObjectResult>(result);
|
||||
indexResult.Value.Should().BeOfType<About>();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task PostNotSupported()
|
||||
{
|
||||
// Arrange
|
||||
var client = new HttpClientBuilder().Build();
|
||||
var content = new Mock<HttpContent>();
|
||||
|
||||
// Act
|
||||
var response = await client.PostAsync(Endpoint, content.Object);
|
||||
|
||||
// Assert
|
||||
response.StatusCode.Should().Be(HttpStatusCode.MethodNotAllowed);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task PutNotSupported()
|
||||
{
|
||||
// Arrange
|
||||
var client = new HttpClientBuilder().Build();
|
||||
var content = new Mock<HttpContent>();
|
||||
|
||||
// Act
|
||||
var response = await client.PutAsync(Endpoint, content.Object);
|
||||
|
||||
// Assert
|
||||
response.StatusCode.Should().Be(HttpStatusCode.MethodNotAllowed);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task PatchNotSupported()
|
||||
{
|
||||
// Arrange
|
||||
var client = new HttpClientBuilder().Build();
|
||||
var content = new Mock<HttpContent>();
|
||||
|
||||
// Act
|
||||
var response = await client.PatchAsync(Endpoint, content.Object);
|
||||
|
||||
// Assert
|
||||
response.StatusCode.Should().Be(HttpStatusCode.MethodNotAllowed);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task DeleteNotSupported()
|
||||
{
|
||||
// Arrange
|
||||
var client = new HttpClientBuilder().Build();
|
||||
|
||||
// Act
|
||||
var response = await client.DeleteAsync(Endpoint);
|
||||
|
||||
// Assert
|
||||
response.StatusCode.Should().Be(HttpStatusCode.MethodNotAllowed);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,135 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using FluentAssertions;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Moq;
|
||||
using Steeltoe.InitializrApi.Controllers;
|
||||
using Steeltoe.InitializrApi.Models;
|
||||
using Steeltoe.InitializrApi.Services;
|
||||
using Steeltoe.InitializrApi.Test.TestUtils;
|
||||
using Xunit;
|
||||
|
||||
namespace Steeltoe.InitializrApi.Test.Controllers
|
||||
{
|
||||
public class ConfigurationControllerTest
|
||||
{
|
||||
private const string Endpoint = "/api/configuration";
|
||||
|
||||
[Fact]
|
||||
public async Task GetConfiguration()
|
||||
{
|
||||
// Arrange
|
||||
var config = new InitializrApiConfiguration();
|
||||
var mockRepo = new Mock<IConfigurationRepository>();
|
||||
mockRepo.Setup(repo => repo.GetConfiguration()).ReturnsAsync(config);
|
||||
var controller = new ConfigurationController(mockRepo.Object);
|
||||
|
||||
// Act
|
||||
var result = await controller.GetConfiguration();
|
||||
|
||||
// Assert
|
||||
var indexResult = Assert.IsType<OkObjectResult>(result);
|
||||
indexResult.Value.Should().BeSameAs(config);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetMetadata()
|
||||
{
|
||||
// Arrange
|
||||
var config = new InitializrApiConfiguration
|
||||
{
|
||||
Metadata = new ProjectMetadata(),
|
||||
};
|
||||
var mockRepo = new Mock<IConfigurationRepository>();
|
||||
mockRepo.Setup(repo => repo.GetConfiguration()).ReturnsAsync(config);
|
||||
var controller = new ConfigurationController(mockRepo.Object);
|
||||
|
||||
// Act
|
||||
var result = await controller.GetMetadata();
|
||||
|
||||
// Assert
|
||||
var indexResult = Assert.IsType<OkObjectResult>(result);
|
||||
indexResult.Value.Should().BeSameAs(config.Metadata);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task GetTemplates()
|
||||
{
|
||||
// Arrange
|
||||
var config = new InitializrApiConfiguration
|
||||
{
|
||||
Templates = new ProjectTemplateConfiguration[0],
|
||||
};
|
||||
var mockRepo = new Mock<IConfigurationRepository>();
|
||||
mockRepo.Setup(repo => repo.GetConfiguration()).ReturnsAsync(config);
|
||||
var controller = new ConfigurationController(mockRepo.Object);
|
||||
|
||||
// Act
|
||||
var result = await controller.GetTemplates();
|
||||
|
||||
// Assert
|
||||
var indexResult = Assert.IsType<OkObjectResult>(result);
|
||||
indexResult.Value.Should().BeSameAs(config.Templates);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task PostNotSupported()
|
||||
{
|
||||
// Arrange
|
||||
var client = new HttpClientBuilder().Build();
|
||||
var content = new Mock<HttpContent>();
|
||||
|
||||
// Act
|
||||
var response = await client.PostAsync(Endpoint, content.Object);
|
||||
|
||||
// Assert
|
||||
response.StatusCode.Should().Be(HttpStatusCode.MethodNotAllowed);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task PutNotSupported()
|
||||
{
|
||||
// Arrange
|
||||
var client = new HttpClientBuilder().Build();
|
||||
var content = new Mock<HttpContent>();
|
||||
|
||||
// Act
|
||||
var response = await client.PutAsync(Endpoint, content.Object);
|
||||
|
||||
// Assert
|
||||
response.StatusCode.Should().Be(HttpStatusCode.MethodNotAllowed);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task PatchNotSupported()
|
||||
{
|
||||
// Arrange
|
||||
var client = new HttpClientBuilder().Build();
|
||||
var content = new Mock<HttpContent>();
|
||||
|
||||
// Act
|
||||
var response = await client.PatchAsync(Endpoint, content.Object);
|
||||
|
||||
// Assert
|
||||
response.StatusCode.Should().Be(HttpStatusCode.MethodNotAllowed);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task DeleteNotSupported()
|
||||
{
|
||||
// Arrange
|
||||
var client = new HttpClientBuilder().Build();
|
||||
|
||||
// Act
|
||||
var response = await client.DeleteAsync(Endpoint);
|
||||
|
||||
// Assert
|
||||
response.StatusCode.Should().Be(HttpStatusCode.MethodNotAllowed);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,119 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.IO;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using FluentAssertions;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using Moq;
|
||||
using Steeltoe.InitializrApi.Controllers;
|
||||
using Steeltoe.InitializrApi.Models;
|
||||
using Steeltoe.InitializrApi.Services;
|
||||
using Steeltoe.InitializrApi.Test.TestUtils;
|
||||
using Xunit;
|
||||
|
||||
namespace Steeltoe.InitializrApi.Test.Controllers
|
||||
{
|
||||
public class ProjectControllerTest
|
||||
{
|
||||
private const string Endpoint = "/api/project";
|
||||
|
||||
[Fact]
|
||||
public async Task GetReturnsProjectArchive()
|
||||
{
|
||||
// Arrange
|
||||
var controller = new ProjectControllerBuilder().Build();
|
||||
var spec = new ProjectSpecification
|
||||
{
|
||||
Name = "someProject",
|
||||
};
|
||||
|
||||
// Act
|
||||
var unknown = await controller.Get(spec);
|
||||
|
||||
// Assert
|
||||
var result = Assert.IsType<FileContentResult>(unknown);
|
||||
result.ContentType.Should().Be("application/zip");
|
||||
result.FileDownloadName.Should().Be("someProject.zip");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task PostReturnsMethodNotAllowed()
|
||||
{
|
||||
// Arrange
|
||||
var client = new HttpClientBuilder().Build();
|
||||
var content = new Mock<HttpContent>();
|
||||
|
||||
// Act
|
||||
var response = await client.PostAsync(Endpoint, content.Object);
|
||||
|
||||
// Assert
|
||||
response.StatusCode.Should().Be(HttpStatusCode.MethodNotAllowed);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task PutReturnsMethodNotAllowed()
|
||||
{
|
||||
// Arrange
|
||||
var client = new HttpClientBuilder().Build();
|
||||
var content = new Mock<HttpContent>();
|
||||
|
||||
// Act
|
||||
var response = await client.PutAsync(Endpoint, content.Object);
|
||||
|
||||
// Assert
|
||||
response.StatusCode.Should().Be(HttpStatusCode.MethodNotAllowed);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task PatchReturnsMethodNotAllowed()
|
||||
{
|
||||
// Arrange
|
||||
var client = new HttpClientBuilder().Build();
|
||||
var content = new Mock<HttpContent>();
|
||||
|
||||
// Act
|
||||
var response = await client.PatchAsync(Endpoint, content.Object);
|
||||
|
||||
// Assert
|
||||
response.StatusCode.Should().Be(HttpStatusCode.MethodNotAllowed);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task DeleteReturnsMethodNotAllowed()
|
||||
{
|
||||
// Arrange
|
||||
var client = new HttpClientBuilder().Build();
|
||||
|
||||
// Act
|
||||
var response = await client.DeleteAsync(Endpoint);
|
||||
|
||||
// Assert
|
||||
response.StatusCode.Should().Be(HttpStatusCode.MethodNotAllowed);
|
||||
}
|
||||
|
||||
class ProjectControllerBuilder
|
||||
{
|
||||
private readonly ProjectController _projectController;
|
||||
|
||||
internal ProjectControllerBuilder()
|
||||
{
|
||||
var mockGenerator = new Mock<IProjectGenerator>();
|
||||
mockGenerator.Setup(g => g.GenerateProject(It.IsAny<ProjectSpecification>()))
|
||||
.ReturnsAsync(new MemoryStream());
|
||||
_projectController = new ProjectController(mockGenerator.Object, new NullLogger<ProjectController>());
|
||||
}
|
||||
|
||||
internal ProjectController Build()
|
||||
{
|
||||
_projectController.ControllerContext.HttpContext = new DefaultHttpContext();
|
||||
return _projectController;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Threading.Tasks;
|
||||
using FluentAssertions;
|
||||
using Steeltoe.InitializrApi.Generators;
|
||||
using Steeltoe.InitializrApi.Models;
|
||||
using Xunit;
|
||||
|
||||
namespace Steeltoe.InitializrApi.Test.Generators
|
||||
{
|
||||
public class StubbleProjectGeneratorTest
|
||||
{
|
||||
[Fact]
|
||||
public async Task GenerateProject()
|
||||
{
|
||||
// Arrange
|
||||
var spec = new ProjectSpecification();
|
||||
var generator = new StubbleProjectGenerator();
|
||||
|
||||
// Act
|
||||
var stream = await generator.GenerateProject(spec);
|
||||
|
||||
// Assert
|
||||
stream.Should().NotBeNull();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
using System.Net;
|
||||
using System.Threading.Tasks;
|
||||
using FluentAssertions;
|
||||
using Steeltoe.InitializrApi.Test.TestUtils;
|
||||
using Xunit;
|
||||
|
||||
namespace Steeltoe.InitializrApi.Test
|
||||
{
|
||||
public class HttpTest
|
||||
{
|
||||
[Fact]
|
||||
public async Task NotFound()
|
||||
{
|
||||
// Arrange
|
||||
var client = new HttpClientBuilder().Build();
|
||||
|
||||
// Act
|
||||
var response = await client.GetAsync("no such path");
|
||||
|
||||
// Assert
|
||||
response.StatusCode.Should().Be(HttpStatusCode.NotFound);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,31 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using FluentAssertions;
|
||||
using Steeltoe.InitializrApi.Models;
|
||||
using Xunit;
|
||||
|
||||
namespace Steeltoe.InitializrApi.Test.Models
|
||||
{
|
||||
public class AboutTest
|
||||
{
|
||||
[Fact]
|
||||
public void Properties()
|
||||
{
|
||||
var about = new About
|
||||
{
|
||||
Name = "some name",
|
||||
Vendor = "some vendor",
|
||||
Url = "some url",
|
||||
Version = "some version",
|
||||
Commit = "some commit",
|
||||
};
|
||||
about.Name.Should().Be("some name");
|
||||
about.Vendor.Should().Be("some vendor");
|
||||
about.Url.Should().Be("some url");
|
||||
about.Version.Should().Be("some version");
|
||||
about.Commit.Should().Be("some commit");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,38 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using FluentAssertions;
|
||||
using Steeltoe.InitializrApi.Models;
|
||||
using Xunit;
|
||||
|
||||
namespace Steeltoe.InitializrApi.Test.Models
|
||||
{
|
||||
public class InitializrApiConfigurationTest
|
||||
{
|
||||
[Fact]
|
||||
public void Properties()
|
||||
{
|
||||
var config = new InitializrApiConfiguration
|
||||
{
|
||||
Metadata = new ProjectMetadata
|
||||
{
|
||||
Name = new ProjectMetadata.Text
|
||||
{
|
||||
Default = "a metadata name",
|
||||
},
|
||||
},
|
||||
Templates = new[]
|
||||
{
|
||||
new ProjectTemplateConfiguration
|
||||
{
|
||||
Uri = new Uri("file:///a uri"),
|
||||
},
|
||||
},
|
||||
};
|
||||
config.Metadata.Name.Default.Should().Be("a metadata name");
|
||||
config.Templates[0].Uri.Should().Be("file:///a uri");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,147 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using FluentAssertions;
|
||||
using Steeltoe.InitializrApi.Models;
|
||||
using Xunit;
|
||||
|
||||
namespace Steeltoe.InitializrApi.Test.Models
|
||||
{
|
||||
public class ProjectMetadataTest
|
||||
{
|
||||
[Fact]
|
||||
public void Properties()
|
||||
{
|
||||
var metadata = new ProjectMetadata
|
||||
{
|
||||
Name = new ProjectMetadata.Text
|
||||
{
|
||||
Type = "a name type",
|
||||
Default = "a name default",
|
||||
},
|
||||
Description = new ProjectMetadata.Text
|
||||
{
|
||||
Type = "a description type",
|
||||
Default = "a description default",
|
||||
},
|
||||
SteeltoeVersion = new ProjectMetadata.SingleSelectList
|
||||
{
|
||||
Type = "a steeltoe version type",
|
||||
Default = "a steeltoe version default",
|
||||
Values = new[]
|
||||
{
|
||||
new ProjectMetadata.SelectItem
|
||||
{
|
||||
Id = "a steeltoe version id",
|
||||
Name = "a steeltoe version name",
|
||||
},
|
||||
}
|
||||
},
|
||||
DotNetVersion = new ProjectMetadata.SingleSelectList
|
||||
{
|
||||
Type = "a dotnet version type",
|
||||
Default = "a dotnet version default",
|
||||
Values = new[]
|
||||
{
|
||||
new ProjectMetadata.SelectItem
|
||||
{
|
||||
Id = "a dotnet version id",
|
||||
Name = "a dotnet version name",
|
||||
},
|
||||
}
|
||||
},
|
||||
Type = new ProjectMetadata.SingleSelectList
|
||||
{
|
||||
Type = "a dotnet template type type",
|
||||
Default = "a dotnet template type default",
|
||||
Values = new[]
|
||||
{
|
||||
new ProjectMetadata.SelectItem
|
||||
{
|
||||
Id = "a dotnet template type id",
|
||||
Name = "a dotnet template type name",
|
||||
},
|
||||
}
|
||||
},
|
||||
Language = new ProjectMetadata.SingleSelectList
|
||||
{
|
||||
Type = "a language type",
|
||||
Default = "a language default",
|
||||
Values = new[]
|
||||
{
|
||||
new ProjectMetadata.SelectItem
|
||||
{
|
||||
Id = "a language id",
|
||||
Name = "a language name",
|
||||
},
|
||||
}
|
||||
},
|
||||
Format = new ProjectMetadata.SingleSelectList
|
||||
{
|
||||
Type = "a project bundle archive format type",
|
||||
Default = "a project bundle archive format default",
|
||||
Values = new[]
|
||||
{
|
||||
new ProjectMetadata.SelectItem
|
||||
{
|
||||
Id = "a project bundle archive format id",
|
||||
Name = "a project bundle archive format name",
|
||||
},
|
||||
}
|
||||
},
|
||||
Dependencies = new ProjectMetadata.GroupList
|
||||
{
|
||||
Type = "a dependencies type",
|
||||
Values = new[]
|
||||
{
|
||||
new ProjectMetadata.Group
|
||||
{
|
||||
Name = "a dependency group name",
|
||||
Values = new[]
|
||||
{
|
||||
new ProjectMetadata.GroupItem
|
||||
{
|
||||
Id = "a dependency id",
|
||||
Name = "a dependency name",
|
||||
Description = "a dependency description",
|
||||
SteeltoeVersionRange = "a dependency steeltoe version range",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
};
|
||||
metadata.Name.Type.Should().Be("a name type");
|
||||
metadata.Name.Default.Should().Be("a name default");
|
||||
metadata.Description.Type.Should().Be("a description type");
|
||||
metadata.Description.Default.Should().Be("a description default");
|
||||
metadata.SteeltoeVersion.Type.Should().Be("a steeltoe version type");
|
||||
metadata.SteeltoeVersion.Default.Should().Be("a steeltoe version default");
|
||||
metadata.SteeltoeVersion.Values[0].Id.Should().Be("a steeltoe version id");
|
||||
metadata.SteeltoeVersion.Values[0].Name.Should().Be("a steeltoe version name");
|
||||
metadata.DotNetVersion.Type.Should().Be("a dotnet version type");
|
||||
metadata.DotNetVersion.Default.Should().Be("a dotnet version default");
|
||||
metadata.DotNetVersion.Values[0].Id.Should().Be("a dotnet version id");
|
||||
metadata.DotNetVersion.Values[0].Name.Should().Be("a dotnet version name");
|
||||
metadata.Type.Type.Should().Be("a dotnet template type type");
|
||||
metadata.Type.Default.Should().Be("a dotnet template type default");
|
||||
metadata.Type.Values[0].Id.Should().Be("a dotnet template type id");
|
||||
metadata.Type.Values[0].Name.Should().Be("a dotnet template type name");
|
||||
metadata.Language.Type.Should().Be("a language type");
|
||||
metadata.Language.Default.Should().Be("a language default");
|
||||
metadata.Language.Values[0].Id.Should().Be("a language id");
|
||||
metadata.Language.Values[0].Name.Should().Be("a language name");
|
||||
metadata.Format.Type.Should().Be("a project bundle archive format type");
|
||||
metadata.Format.Default.Should().Be("a project bundle archive format default");
|
||||
metadata.Format.Values[0].Id.Should().Be("a project bundle archive format id");
|
||||
metadata.Format.Values[0].Name.Should().Be("a project bundle archive format name");
|
||||
metadata.Dependencies.Type.Should().Be("a dependencies type");
|
||||
metadata.Dependencies.Values[0].Name.Should().Be("a dependency group name");
|
||||
metadata.Dependencies.Values[0].Values[0].Id.Should().Be("a dependency id");
|
||||
metadata.Dependencies.Values[0].Values[0].Name.Should().Be("a dependency name");
|
||||
metadata.Dependencies.Values[0].Values[0].Description.Should().Be("a dependency description");
|
||||
metadata.Dependencies.Values[0].Values[0].SteeltoeVersionRange.Should().Be("a dependency steeltoe version range");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,33 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using FluentAssertions;
|
||||
using Steeltoe.InitializrApi.Models;
|
||||
using Xunit;
|
||||
|
||||
namespace Steeltoe.InitializrApi.Test.Models
|
||||
{
|
||||
public class ProjectSpecificationTest
|
||||
{
|
||||
[Fact]
|
||||
public void Properties()
|
||||
{
|
||||
var spec = new ProjectSpecification
|
||||
{
|
||||
Name = "some name",
|
||||
Description = "some description",
|
||||
SteeltoeVersion = "some Steeltoe release ID",
|
||||
DotnetTargetFrameworkId = "some DotNet framework ID",
|
||||
DotnetLanguageId = "some DotNet language ID",
|
||||
DotnetTemplateId = "some DotNet template ID",
|
||||
};
|
||||
spec.Name.Should().Be("some name");
|
||||
spec.Description.Should().Be("some description");
|
||||
spec.SteeltoeVersion.Should().Be("some Steeltoe release ID");
|
||||
spec.DotnetTargetFrameworkId.Should().Be("some DotNet framework ID");
|
||||
spec.DotnetLanguageId.Should().Be("some DotNet language ID");
|
||||
spec.DotnetTemplateId.Should().Be("some DotNet template ID");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using FluentAssertions;
|
||||
using Steeltoe.InitializrApi.Models;
|
||||
using Xunit;
|
||||
|
||||
namespace Steeltoe.InitializrApi.Test.Models
|
||||
{
|
||||
public class ProjectTemplateConfigurationTest
|
||||
{
|
||||
[Fact]
|
||||
public void Properties()
|
||||
{
|
||||
var config = new ProjectTemplateConfiguration
|
||||
{
|
||||
Uri = new Uri("file:///a uri"),
|
||||
SteeltoeVersionRange = "a steeltoe version range",
|
||||
DotNetVersionRange = "a dotnet version range",
|
||||
Type = "a dotnet template type",
|
||||
Language = "a language",
|
||||
};
|
||||
config.Uri.Should().Be("file:///a uri");
|
||||
config.SteeltoeVersionRange.Should().Be("a steeltoe version range");
|
||||
config.DotNetVersionRange.Should().Be("a dotnet version range");
|
||||
config.Type.Should().Be("a dotnet template type");
|
||||
config.Language.Should().Be("a language");
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,54 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using FluentAssertions;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Logging.Abstractions;
|
||||
using Steeltoe.InitializrApi.Controllers;
|
||||
using Steeltoe.InitializrApi.Services;
|
||||
using Xunit;
|
||||
|
||||
namespace Steeltoe.InitializrApi.Test
|
||||
{
|
||||
public class StartupTest
|
||||
{
|
||||
[Fact]
|
||||
public void ConfigurationControllerRegistered()
|
||||
{
|
||||
// Arrange
|
||||
var cfg = new ConfigurationBuilder().Build();
|
||||
var startup = new Startup(cfg);
|
||||
IServiceCollection svcs = new ServiceCollection();
|
||||
svcs.AddSingleton<ILogger<IConfigurationRepository>>(new NullLogger<IConfigurationRepository>());
|
||||
startup.ConfigureServices(svcs);
|
||||
|
||||
// Act
|
||||
svcs.AddTransient<ConfigurationController>();
|
||||
|
||||
// Assert
|
||||
var controller = svcs.BuildServiceProvider().GetService<ConfigurationController>();
|
||||
controller.Should().NotBeNull();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void ProjectControllerRegisterer()
|
||||
{
|
||||
// Arrange
|
||||
var cfg = new ConfigurationBuilder().Build();
|
||||
var startup = new Startup(cfg);
|
||||
IServiceCollection svcs = new ServiceCollection();
|
||||
svcs.AddSingleton<ILogger<ProjectController>>(new NullLogger<ProjectController>());
|
||||
startup.ConfigureServices(svcs);
|
||||
|
||||
// Act
|
||||
svcs.AddTransient<ProjectController>();
|
||||
|
||||
// Assert
|
||||
var controller = svcs.BuildServiceProvider().GetService<ProjectController>();
|
||||
controller.Should().NotBeNull();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,17 +0,0 @@
|
|||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\InitializrApi\Steeltoe.InitializrApi.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="3.1.5" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="..\Directory.Build.props">
|
||||
<Link>Directory.Build.props</Link>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
|
@ -1,31 +0,0 @@
|
|||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the Apache 2.0 License.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Net.Http;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.TestHost;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
|
||||
namespace Steeltoe.InitializrApi.Test.TestUtils
|
||||
{
|
||||
public class HttpClientBuilder
|
||||
{
|
||||
private static readonly IHost Host;
|
||||
|
||||
static HttpClientBuilder()
|
||||
{
|
||||
var hostBuilder = new HostBuilder().ConfigureWebHost(webHost =>
|
||||
{
|
||||
webHost.UseTestServer();
|
||||
webHost.UseStartup<Startup>();
|
||||
});
|
||||
Host = hostBuilder.Start();
|
||||
}
|
||||
|
||||
public HttpClient Build()
|
||||
{
|
||||
return Host.GetTestClient();
|
||||
}
|
||||
}
|
||||
}
|
Загрузка…
Ссылка в новой задаче