Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(mock-server): add mock-server api #83

Closed
wants to merge 38 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
38 commits
Select commit Hold shift + click to select a range
954b428
chore: merge master into develop (#60)
alex-held Dec 28, 2019
2dc46a0
refactor(ci): add nuget package release pipeline (#61)
alex-held Dec 28, 2019
7449418
feat(mock-server): add mock-server api
alex-held Dec 28, 2019
9e57466
feat(mock-server): match request
alex-held Dec 28, 2019
da7a1db
feat(mock-server): match request by header
alex-held Dec 28, 2019
942821b
Merge branch 'master' into develop
alex-held Dec 28, 2019
1eeada8
Merge branch 'develop' into feature/mock-server
alex-held Dec 28, 2019
9b36a5c
feat(mock-server): match request by string body
alex-held Dec 30, 2019
264d1bd
style: apply ReSharper code-styless
alex-held Dec 30, 2019
9547c55
refactor(mock-server): add test for SetupService :white_check_mark:
alex-held Dec 30, 2019
f1743aa
feat(mock-server): match request by query string
alex-held Dec 30, 2019
d5cbd84
refactor(mock-server): wrap ISetupRepository in ISetupService
alex-held Jan 4, 2020
b99e8cf
!refactor(mock-server): determine admin area from port
alex-held Jan 4, 2020
4089188
feat(mock-server): add docker support
alex-held Jan 4, 2020
538f3ad
styles: apply ReSharper code styles
alex-held Jan 4, 2020
306fe10
refactor(mock-server): annotate non/-nullable reference types
alex-held Jan 4, 2020
2387bde
refactor(mock-server): create setups via SetupController
alex-held Jan 4, 2020
592dec1
refactor(mock-server): use ports 80 (matching) + 1080 (admin)
alex-held Jan 4, 2020
83d657e
chore(git-flow): merge master into develop (#67)
alex-held Jan 5, 2020
9715b3f
Merge branch 'feature/mock-server' into develop
alex-held Jan 5, 2020
79b86fb
chore(git-flow) merge develop into feature/mock-server (#68)
alex-held Jan 5, 2020
6842717
chore(deps): bump Microsoft.NET.Test.Sdk
alex-held Jan 5, 2020
1b94fcb
refactor(mock-server): use ports 80 (matching) + 1080 (admin)
alex-held Jan 5, 2020
fa45260
Merge branch 'develop' into feature/mock-server
alex-held Jan 6, 2020
95bbb15
feat(mock-server): serialize json / yaml files into Setups
alex-held Jan 6, 2020
35ca7c8
refactor(mock-server): add [DebuggerDisplay]
alex-held Jan 6, 2020
1b53d12
refactor(mock-server): add [DebuggerDisplay]
alex-held Jan 6, 2020
d2dc5ba
Merge branch 'feature/mock-server' of github.com:alex-held/NinjaTools…
alex-held Jan 6, 2020
e4001d8
feat(mock-server): add support to configure it using yaml / json files
alex-held Jan 7, 2020
511bc76
refactor(mock-server): remove dead code
alex-held Jan 7, 2020
041b9e9
refactor(mock-server): initialize configurations from filesystem at s…
alex-held Jan 10, 2020
e140af5
chore: add coverlet.msbuild to collect code coverage
alex-held Jan 10, 2020
0f2f8c4
Merge branch 'develop' into feature/mock-server
alex-held Jan 10, 2020
ed91b9c
ci: collect coverage for SonarCloud
alex-held Jan 10, 2020
8f6dd57
style: apply code styles
alex-held Jan 10, 2020
ab28f95
refactor(mock-server): set mock-server root path to /etc/mock-server
alex-held Jan 10, 2020
9f33094
feat(mock-server): add swagger support
alex-held Jan 10, 2020
2fa8c12
feat(mock-server): add swagger support
alex-held Jan 10, 2020
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 14 additions & 3 deletions NinjaTools.FluentMockServer.sln
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@ EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NinjaTools.FluentMockServer.Tests", "test\NinjaTools.FluentMockServer.Tests\NinjaTools.FluentMockServer.Tests.csproj", "{72FDC041-D690-45C9-9B3A-A48EC676DC37}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "scripts", "scripts", "{05E960F6-8585-4DC2-B04D-1C43CFE47C22}"
ProjectSection(SolutionItems) = preProject
scripts\docker-compore.dependencies.yml = scripts\docker-compore.dependencies.yml
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NinjaTools.FluentMockServer.API", "src\NinjaTools.FluentMockServer.API\NinjaTools.FluentMockServer.API.csproj", "{C60E5A2A-4391-420B-8FBC-D7E941EEF286}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NinjaTools.FluentMockServer.API.Tests", "test\NinjaTools.FluentMockServer.API.Tests\NinjaTools.FluentMockServer.API.Tests.csproj", "{175B41A0-DF12-499C-AD27-9E4EC09A82DA}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Expand All @@ -40,11 +41,21 @@ Global
{72FDC041-D690-45C9-9B3A-A48EC676DC37}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{72FDC041-D690-45C9-9B3A-A48EC676DC37}.Debug|Any CPU.Build.0 = Debug|Any CPU
{72FDC041-D690-45C9-9B3A-A48EC676DC37}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C60E5A2A-4391-420B-8FBC-D7E941EEF286}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C60E5A2A-4391-420B-8FBC-D7E941EEF286}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C60E5A2A-4391-420B-8FBC-D7E941EEF286}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C60E5A2A-4391-420B-8FBC-D7E941EEF286}.Release|Any CPU.Build.0 = Release|Any CPU
{175B41A0-DF12-499C-AD27-9E4EC09A82DA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{175B41A0-DF12-499C-AD27-9E4EC09A82DA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{175B41A0-DF12-499C-AD27-9E4EC09A82DA}.Release|Any CPU.ActiveCfg = Release|Any CPU
{175B41A0-DF12-499C-AD27-9E4EC09A82DA}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{4E080C86-373B-47ED-81C3-2B8CD0A424D7} = {1BBF6811-5858-47A7-A382-29D777150068}
{E9883692-C8F8-4CA9-8EDB-7859809D8DB8} = {820DD7E9-2777-4D4B-93E0-59711107B4EF}
{4E051198-705E-4605-8EEE-951D05E4B860} = {820DD7E9-2777-4D4B-93E0-59711107B4EF}
{72FDC041-D690-45C9-9B3A-A48EC676DC37} = {1BBF6811-5858-47A7-A382-29D777150068}
{C60E5A2A-4391-420B-8FBC-D7E941EEF286} = {820DD7E9-2777-4D4B-93E0-59711107B4EF}
{175B41A0-DF12-499C-AD27-9E4EC09A82DA} = {1BBF6811-5858-47A7-A382-29D777150068}
EndGlobalSection
EndGlobal
18 changes: 1 addition & 17 deletions build/templates/build.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,31 +15,15 @@ jobs:
clean: false
submodules: recursive
persistCredentials: true

- task: SonarCloudPrepare@1
inputs:
SonarCloud: 'SonarCloud'
organization: 'alex-held'
scannerMode: 'MSBuild'
projectKey: 'alex-held_NinjaTools.FluentMockServer'
projectName: 'NinjaTools.FluentMockServer'


- task: UseDotNet@2
inputs:
packageType: 'sdk'
version: ${{ parameters.sdkVersion }}
includePreviewVersions: true

- task: UseDotNet@2
inputs:
packageType: 'sdk'
version: '2.0.0' # SonarCloud
includePreviewVersions: true

- task: DotNetCoreCLI@2
inputs:
command: 'build'
projects: ${{ parameters.projects }}
arguments: '--configuration ${{ parameters.buildConfiguration }}'

- task: SonarCloudAnalyze@1
24 changes: 24 additions & 0 deletions build/templates/test-cover.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,37 @@ jobs:
clean: false
submodules: recursive
persistCredentials: true

- task: SonarCloudPrepare@1
inputs:
SonarCloud: 'SonarCloud'
organization: 'alex-held'
scannerMode: 'MSBuild'
projectKey: 'alex-held_NinjaTools.FluentMockServer'
projectName: 'NinjaTools.FluentMockServer'
extraProperties: |
sonar.exclusions=**/obj/**,**/*.dll
sonar.cs.opencover.reportsPaths=$(Build.SourcesDirectory)/**/coverage.opencover.xml
sonar.cs.vstest.reportsPaths=$(Agent.TempDirectory)/*.trx


- task: UseDotNet@2
inputs:
packageType: 'sdk'
version: ${{ parameters.sdkVersion }}
includePreviewVersions: true

- task: UseDotNet@2
inputs:
packageType: 'sdk'
version: '2.0.0' # SonarCloud
includePreviewVersions: true

- task: DotNetCoreCLI@2
inputs:
testRunTitle: "run unit tests"
command: "test"
projects: ${{ parameters.projects }}
arguments: '/p:CollectCoverage=true /p:CoverletOutputFormat=opencover --logger trx'

- task: SonarCloudAnalyze@1
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace NinjaTools.FluentMockServer.API.Administration
{
public class AdminOptions
{
public int Port { get; set; }
}
}
50 changes: 50 additions & 0 deletions src/NinjaTools.FluentMockServer.API/Configuration/ConfigFile.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
using System;
using System.ComponentModel.DataAnnotations;
using System.Diagnostics;
using System.Globalization;
using JetBrains.Annotations;
using Newtonsoft.Json;
using NinjaTools.FluentMockServer.API.Models;
using YamlDotNet.Serialization;

namespace NinjaTools.FluentMockServer.API.Configuration
{
[DebuggerDisplay("{DebuggerDisplay(), nq}")]
public class ConfigFile : IConfigFile
{
[JsonConstructor]
public ConfigFile([NotNull] string path, [NotNull] params Setup[] setups)
{
Path = path;

var fileExtension = System.IO.Path.GetExtension(Path).TrimStart('.').ToLower(CultureInfo.InvariantCulture);
if (Enum.TryParse<ConfigurationFileType>(fileExtension, out var fileType))
{
FileType = fileType;
}

Configurations = new ConfigurationCollection(setups);
}

[JsonIgnore]
[YamlIgnore]
public string Path { get; }

[JsonIgnore]
[YamlIgnore]
public ConfigurationFileType? FileType { get; }

[NotNull]
[Required]
[JsonRequired]
public ConfigurationCollection Configurations { get; }

[NotNull]
private string DebuggerDisplay()
{
var count = (this as IConfigFile).Count;
var fileType = FileType.HasValue ? FileType.ToString() : "Unkown filetype!";
return $"Count: {count.ToString()}; Path={Path}; FileType={fileType}";
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Abstractions;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Newtonsoft.Json.Linq;
using NinjaTools.FluentMockServer.API.Models;
using YamlDotNet.Serialization;

namespace NinjaTools.FluentMockServer.API.Configuration
{
/// <summary>
/// Runtime options for the MockServer
/// </summary>
public class MockServerOptions
{
public string ConfigFilePath { get; set; } = "/etc/mock-server/config/";
}

public interface IConfigFileProvider
{
IEnumerable<IConfigFile> GetConfigFiles();
}

public class ConfigFileProvider : IConfigFileProvider
{
private readonly IFileSystem _fs;
private readonly ILogger<ConfigFileProvider> _logger;
private readonly MockServerOptions _options;

public ConfigFileProvider(IFileSystem fs, ILogger<ConfigFileProvider> logger, IOptions<MockServerOptions> options)
{
_fs = fs;
_logger = logger;
_options = options.Value;
}

public ConfigFileProvider( ILogger<ConfigFileProvider> logger, IOptions<MockServerOptions> options)
: this(new FileSystem(), logger, options)
{
}


public IEnumerable<IConfigFile> GetConfigFiles()
{
var rootDirectory = _options.ConfigFilePath;
var files = _fs.Directory.GetFiles(rootDirectory, "*", SearchOption.AllDirectories);

foreach (var file in files)
{
var fileExtension = _fs.Path.GetExtension(file).TrimStart('.').ToLower();

if (Enum.TryParse<ConfigurationFileType>(fileExtension, out var fileType))
{
foreach (var configFile in ParseConfigFile(fileType, file))
{
yield return configFile;
}
}
else
{
_logger.LogError($"The file extension {fileExtension} is not supported yet.");
}
}
}

private ConfigFile ParseJson(string path)
{
var jo = JArray.Parse(_fs.File.ReadAllText(path));
var setups = jo.ToObject<List<Setup>>();

return new ConfigFile(path, setups.ToArray());
}

private IConfigFile ParseYaml(string path)
{
using var reader = new StringReader(_fs.File.ReadAllText(path));
var deserializer = new DeserializerBuilder().Build();

var setups = deserializer.Deserialize<List<Setup>>(reader);
return new ConfigFile(path, setups.ToArray());
}


private IEnumerable<IConfigFile> ParseConfigFile(ConfigurationFileType fileType, string file)
{
if (fileType == ConfigurationFileType.yaml)
{
yield return ParseYaml(file);
}
else if (fileType == ConfigurationFileType.json)
{
yield return ParseJson(file);
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
using System.Collections.Generic;
using System.Diagnostics;
using JetBrains.Annotations;
using Newtonsoft.Json;
using NinjaTools.FluentMockServer.API.Models;

namespace NinjaTools.FluentMockServer.API.Configuration
{

[JsonArray(AllowNullItems = false)]
[DebuggerDisplay("{DebuggerDisplay(), nq}")]
public class ConfigurationCollection : List<Setup>
{
public ConfigurationCollection()
{

}

public ConfigurationCollection(params Setup[]? setups) : this()
{
AddRange(setups);
}

[NotNull]
private string DebuggerDisplay()
{
var count = Count;
return $"Count: {count.ToString()}";
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;

namespace NinjaTools.FluentMockServer.API.Configuration
{
[JsonConverter(typeof(StringEnumConverter))]
public enum ConfigurationFileType : int
{
yaml = 1,
yml = 1,
json = 2
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using System.Threading.Tasks;
using NinjaTools.FluentMockServer.API.Services;
using NinjaTools.FluentMockServer.API.Types;

namespace NinjaTools.FluentMockServer.API.Configuration
{
public class ConfigurationInitializer : IInitializer
{
private readonly IConfigurationService _configurationService;

public ConfigurationInitializer(IConfigurationService configurationService)
{
_configurationService = configurationService;
}

/// <inheritdoc />
public Task InitializeAsync()
{
_configurationService.Reload();
return Task.CompletedTask;
}
}
}
25 changes: 25 additions & 0 deletions src/NinjaTools.FluentMockServer.API/Configuration/IConfigFile.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
using JetBrains.Annotations;
using YamlDotNet.Serialization;

namespace NinjaTools.FluentMockServer.API.Configuration
{
public interface IConfigFile
{
[YamlIgnore]
public int Count => Configurations.Count;

[NotNull]
[YamlIgnore]
string Path { get; }

/// <summary>
/// The <see cref="FileType"/> will only be null when we don't support it.
/// </summary>
[CanBeNull]
[YamlIgnore]
public ConfigurationFileType? FileType { get; }

[NotNull]
ConfigurationCollection Configurations { get; }
}
}
35 changes: 35 additions & 0 deletions src/NinjaTools.FluentMockServer.API/Controllers/SetupController.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using System.Collections.Generic;
using System.Threading.Tasks;
using JetBrains.Annotations;
using Microsoft.AspNetCore.Mvc;
using NinjaTools.FluentMockServer.API.Models;
using NinjaTools.FluentMockServer.API.Services;

namespace NinjaTools.FluentMockServer.API.Controllers
{
[ApiController]
[Route("setup")]
public class SetupController : ControllerBase
{
private readonly ISetupService _setupService;

public SetupController(ISetupService setupService)
{
_setupService = setupService;
}

[HttpGet("list")]
public IEnumerable<Setup> List()
{
var setups = _setupService.GetAll();
return setups;
}

[HttpPost("create")]
public Task<Setup> Create([NotNull] Setup setup)
{
_setupService.Add(setup);
return Task.FromResult(setup);
}
}
}
Loading