This commit is contained in:
hananiel 2019-09-10 14:12:50 -04:00
Родитель c81cc7fa57
Коммит 3715d3b839
15 изменённых файлов: 276 добавлений и 76 удалений

Просмотреть файл

@ -131,34 +131,35 @@ namespace Steeltoe.Initializr.Services.Mustache
{
var settings = _templateSettings[templateKey];
var files = settings.SourceSets;
var exclusionExpressions = GetExclusionList(dataView, settings.Schema);
var exclusionExpressions = GetInclusionExpressions(dataView, settings.Schema);
var excludedFiles = new List<string>();
foreach (var sourceFile in files)
{
if (sourceFile.Name.EndsWith("mustache.json")
|| sourceFile.Name.EndsWith("sourceExclusions.json"))
if (sourceFile.Name.EndsWith("mustache.json"))
{
continue;
}
// By default everything is included, unless there is a conditional inclusions
// which causes it to be an exclusion when condition is not met.
// Explicit inclusions override exclusions by condition not being met
var explicitInclusions = new List<string>();
foreach (var exclusionExpression in exclusionExpressions)
{
if (exclusionExpression.EndsWith("**"))
if (exclusionExpression.IsMatch(sourceFile.Name))
{
if (sourceFile.Name.StartsWith(exclusionExpression.Replace("/**", string.Empty)))
if (exclusionExpression.IsInclusion)
{
excludedFiles.Add(sourceFile.Name);
explicitInclusions.Add(sourceFile.Name);
}
}
else
{
// exact Match
if (sourceFile.Name == exclusionExpression)
else
{
excludedFiles.Add(sourceFile.Name);
}
}
}
excludedFiles = excludedFiles.Except(explicitInclusions).ToList();
}
return files.Where(f => excludedFiles.All(e => e != f.Name));
@ -180,12 +181,54 @@ namespace Steeltoe.Initializr.Services.Mustache
}
}
private List<string> GetExclusionList(Dictionary<string, string> dataView, MustacheConfigSchema schema)
private List<InclusionExpression> GetInclusionExpressions(Dictionary<string, string> dataView, MustacheConfigSchema schema) =>
schema.ConditionalInclusions
.Select(x => new InclusionExpression(
expression: x.InclusionExpression,
matchesView: dataView.ContainsKey(x.Name) && (dataView[x.Name] is string stringValue && stringValue == "True")))
.ToList();
}
public class InclusionExpression
{
private readonly string _expression;
private readonly bool _matchesView;
public InclusionExpression(string expression, bool matchesView)
{
// This list of expressions that do NOT apply become the exclusion list here
return schema.ConditionalInclusions.Where(x => !dataView.ContainsKey(x.Name)
|| (dataView[x.Name] is string stringValue && stringValue != "True"))
.Select(x => x.InclusionExpression).ToList();
_expression = expression;
_matchesView = matchesView;
}
public bool IsInclusion
{
get { return _matchesView; }
}
public bool IsMatch(string fileName)
{
if (_expression.EndsWith("**"))
{
if (fileName.StartsWith(_expression.Replace("/**", string.Empty))) //unless it is has an explicit inclusion
{
return true;
}
}
else
{
var escapedExpression = _expression.Replace('/', Path.DirectorySeparatorChar);
var exactMatches = escapedExpression.Split(';');
foreach (var match in exactMatches)
{
if (fileName == match)
{
return true;
}
}
}
return false;
}
}
}

Просмотреть файл

@ -1,3 +0,0 @@
{
"AnyEFCore": "Models/**"
}

Просмотреть файл

@ -0,0 +1,88 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Options;
using Steeltoe.Extensions.Configuration.ConfigServer;
using Microsoft.Extensions.Configuration;
namespace {{ProjectNameSpace}}.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class ConfigDataController : ControllerBase
{
private IOptionsSnapshot<ConfigServerData> IConfigServerData { get; set; }
private ConfigServerClientSettingsOptions ConfigServerClientSettingsOptions { get; set; }
private IConfigurationRoot Config { get; set; }
public ConfigDataController(IConfigurationRoot config, IOptionsSnapshot<ConfigServerData> configServerData, IOptions<ConfigServerClientSettingsOptions> confgServerSettings)
{
// The ASP.NET DI mechanism injects the data retrieved from the Spring Cloud Config Server
// as an IOptionsSnapshot<ConfigServerData>. This happens because we added the call to:
// "services.Configure<ConfigServerData>(Configuration);" in the StartUp class
if (configServerData != null)
IConfigServerData = configServerData;
// The settings used in communicating with the Spring Cloud Config Server
if (confgServerSettings != null)
ConfigServerClientSettingsOptions = confgServerSettings.Value;
Config = config;
}
// GET api/values
[HttpGet]
public ActionResult<IDictionary<string, string>> Get()
{
return Ok(CreateConfigServerData());
}
[HttpPost]
public IActionResult Reload()
{
if (Config != null)
{
Config.Reload();
}
return Ok();
}
private IDictionary<string, string> CreateConfigServerData()
{
var configData = new Dictionary<string, string>();
// IConfigServerData property is set to a IOptionsSnapshot<ConfigServerData> that has been
// initialized with the configuration data returned from the Spring Cloud Config Server
if (IConfigServerData != null && IConfigServerData.Value != null)
{
var data = IConfigServerData.Value;
configData["Bar"] = data.Bar ?? "Not returned";
configData["Foo"] = data.Foo ?? "Not returned";
configData["Info.Url"] = "Not returned";
configData["Info.Description"] = "Not returned";
if (data.Info != null)
{
configData["Info.Url"] = data.Info.Url ?? "Not returned";
configData["Info.Description"] = data.Info.Description ?? "Not returned";
}
}
else
{
configData["Bar"] = "Not Available";
configData["Foo"] = "Not Available";
configData["Info.Url"] = "Not Available";
configData["Info.Description"] = "Not Available";
}
return configData;
}
}
}

Просмотреть файл

@ -0,0 +1,25 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace {{ProjectNameSpace}}
{
/// <summary>
/// An object used with the DI Options mechanism for exposing the data retrieved
/// from the Spring Cloud Config Server
/// </summary>
public class ConfigServerData
{
public string Bar { get; set; }
public string Foo { get; set; }
public Info Info { get; set; }
}
public class Info
{
public string Description { get; set; }
public string Url { get; set; }
}
}

Просмотреть файл

@ -15,6 +15,10 @@ using Steeltoe.Extensions.Logging;
using Steeltoe.Extensions.Configuration;
using Steeltoe.Extensions.Configuration.CloudFoundry;
{{/CloudFoundry}}
{{#ConfigServer}}
using Steeltoe.Extensions.Configuration.ConfigServer;
{{/ConfigServer}}
namespace {{ProjectNameSpace}}
{
public class Program
@ -22,10 +26,13 @@ namespace {{ProjectNameSpace}}
public static void Main(string[] args)
{
CreateWebHostBuilder(args)
{{#ConfigServer}}
.AddConfigServer()
{{/ConfigServer}}
.Build()
{{#AnyEFCore}}
.InitializeDbContexts()
{{/AnyEFCore}}
{{/AnyEFCore}}
.Run();
}

Просмотреть файл

@ -25,6 +25,9 @@
{{#CloudFoundry}}
<PackageReference Include="Steeltoe.Extensions.Configuration.CloudFoundryCore" Version="{{SteeltoeVersion}}" />
{{/CloudFoundry}}
{{#ConfigServer}}
<PackageReference Include="Steeltoe.Extensions.Configuration.ConfigServerCore" Version="{{SteeltoeVersion}}" />
{{/ConfigServer}}
{{#ActuatorsOrCloudFoundry}}
<PackageReference Include="Steeltoe.Management.ExporterCore" Version="{{SteeltoeVersion}}"/>

Просмотреть файл

@ -61,6 +61,10 @@ using Steeltoe.CloudFoundry.Connector.OAuth;
{{#PostgresEFCore}}
using Steeltoe.CloudFoundry.Connector.PostgreSql.EFCore;
{{/PostgresEFCore}}
{{#ConfigServer}}
using Steeltoe.Extensions.Configuration.ConfigServer;
{{/ConfigServer}}
namespace {{ProjectNameSpace}}
{
public class Startup
@ -128,6 +132,16 @@ namespace {{ProjectNameSpace}}
{{#SQLServer}}
services.AddDbContext<TestContext>(options => options.UseSqlServer(Configuration));
{{/SQLServer}}
{{#ConfigServer}}
// Optional: Adds ConfigServerClientOptions to service container
services.ConfigureConfigServerClientOptions(Configuration);
// Optional: Adds IConfiguration and IConfigurationRoot to service container
services.AddConfiguration(Configuration);
// Adds the configuration data POCO configured with data returned from the Spring Cloud Config Server
services.Configure<ConfigServerData>(Configuration);
{{/ConfigServer}}
{{#TargetFrameworkVersion22}}
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);
{{/TargetFrameworkVersion22}}

Просмотреть файл

@ -78,6 +78,12 @@
"Description": "Steeltoe: Add Microsoft SQL Server connnectors",
"friendlyName": "SQL Server"
},
{
"Name": "ConfigServer",
"DefaultValue": false,
"Description": "Steeltoe: Add ConfigServer Configuration Source",
"friendlyName": "Config Server"
},
{
"Name": "ProjectNameSpace",
"DefaultValue": "SteeltoeExample",
@ -125,6 +131,10 @@
{
"Name": "AnyEFCore",
"InclusionExpression": "Models/**"
},
{
"Name": "ConfigServer",
"InclusionExpression": "Models/ConfigServerData.cs;Controllers/ConfigDataController.cs"
}
],
"Versions": [

Просмотреть файл

@ -1,3 +0,0 @@
{
"AnyEFCore": "Models/**"
}

Просмотреть файл

@ -1,3 +0,0 @@
{
"AnyEFCore": "Models/**"
}

Просмотреть файл

@ -1,3 +0,0 @@
{
"AnyEFCore": "Models/**"
}

Просмотреть файл

@ -31,13 +31,7 @@ namespace Steeltoe.Initializr.Tests
public AllImplementationsAndTemplates()
{
var settings = new Dictionary<string, string>()
{
["FriendlyNames:CloudFoundry"] = "Cloud Foundry",
};
var configuration = new ConfigurationBuilder()
.AddInMemoryCollection(settings)
.Build();
IConfigurationRoot configuration = TestHelper.GetConfiguration();
var implementations = new ITemplateService[]
{
@ -51,12 +45,12 @@ namespace Steeltoe.Initializr.Tests
};
var templateVersions = (TemplateVersion[])Enum.GetValues(typeof(TemplateVersion));
var data = from implementation in implementations
from templateName in templateNames
from templateVersion in templateVersions
select new object[] { implementation, templateName, templateVersion };
from templateName in templateNames
from templateVersion in templateVersions
select new object[] { implementation, templateName, templateVersion };
_data = data.ToList();
}
public IEnumerator<object[]> GetEnumerator() => _data.GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();

Просмотреть файл

@ -77,7 +77,7 @@ namespace Steeltoe.Initializr.Tests
[ClassData(typeof(AllImplementationsAndTemplates))]
public async Task CreateTemplate_actuators(ITemplateService templateService, string templateName, TemplateVersion version)
{
var files = await templateService.GenerateProjectFiles(new Initializr.Models.GeneratorModel()
var files = await templateService.GenerateProjectFiles(new Models.GeneratorModel()
{
Dependencies = "Actuators",
ProjectName = "testProject",
@ -97,7 +97,7 @@ namespace Steeltoe.Initializr.Tests
[ClassData(typeof(AllImplementationsAndTemplates))]
public async Task CreateTemplate_react(ITemplateService templateService, string templateName, TemplateVersion version)
{
var files = await templateService.GenerateProjectFiles(new Initializr.Models.GeneratorModel()
var files = await templateService.GenerateProjectFiles(new Models.GeneratorModel()
{
ProjectName = "testProject",
TemplateShortName = templateName,
@ -112,7 +112,7 @@ namespace Steeltoe.Initializr.Tests
[ClassData(typeof(AllImplementationsAndTemplates))]
public async Task CreateTemplate_discovery(ITemplateService templateService, string templateName, TemplateVersion version)
{
var files = await templateService.GenerateProjectFiles(new Initializr.Models.GeneratorModel()
var files = await templateService.GenerateProjectFiles(new Models.GeneratorModel()
{
Dependencies = "Discovery",
TemplateShortName = templateName,
@ -132,7 +132,7 @@ namespace Steeltoe.Initializr.Tests
[ClassData(typeof(AllImplementationsAndTemplates))]
public async Task CreateTemplate_actuators_circuitbreakers(ITemplateService templateService, string templateName, TemplateVersion version)
{
var files = await templateService.GenerateProjectFiles(new Initializr.Models.GeneratorModel()
var files = await templateService.GenerateProjectFiles(new Models.GeneratorModel()
{
Dependencies = "Actuators,CircuitBreaker",
TemplateShortName = templateName,
@ -148,7 +148,7 @@ namespace Steeltoe.Initializr.Tests
[ClassData(typeof(AllImplementationsAndTemplates))]
public async Task CreateTemplate_MySql(ITemplateService templateService, string templateName, TemplateVersion version)
{
var files = await templateService.GenerateProjectFiles(new Initializr.Models.GeneratorModel()
var files = await templateService.GenerateProjectFiles(new Models.GeneratorModel()
{
Dependencies = "MySql",
TemplateShortName = templateName,
@ -165,7 +165,7 @@ namespace Steeltoe.Initializr.Tests
[ClassData(typeof(AllImplementationsAndTemplates))]
public async Task CreateTemplate_MySql_EFCore(ITemplateService templateService, string templateName, TemplateVersion version)
{
var files = await templateService.GenerateProjectFiles(new Initializr.Models.GeneratorModel()
var files = await templateService.GenerateProjectFiles(new Models.GeneratorModel()
{
Dependencies = "MySqlEFCore",
TemplateShortName = templateName,
@ -181,7 +181,7 @@ namespace Steeltoe.Initializr.Tests
[ClassData(typeof(AllImplementationsAndTemplates))]
public async Task CreateTemplate_postgresql(ITemplateService templateService, string templateName, TemplateVersion version)
{
var files = await templateService.GenerateProjectFiles(new Initializr.Models.GeneratorModel()
var files = await templateService.GenerateProjectFiles(new Models.GeneratorModel()
{
Dependencies = "Postgres",
TemplateShortName = templateName,
@ -194,11 +194,35 @@ namespace Steeltoe.Initializr.Tests
Assert.Contains("services.AddPostgresConnection(Configuration);", startUpContents);
}
[Fact]
public async Task CreateTemplate_ConfigServer()
{
var configuration = TestHelper.GetConfiguration();
var logger = new LoggerFactory().CreateLogger<MustacheTemplateService>();
ITemplateService templateService = new MustacheTemplateService(configuration, logger);
var files = await templateService.GenerateProjectFiles(new Models.GeneratorModel()
{
Dependencies = "ConfigServer",
TemplateShortName = "Steeltoe-WebApi",
TemplateVersion = TemplateVersion.V2,
});
Assert.DoesNotContain(files, file => file.Key.EndsWith("SampleData.cs"));
Assert.Contains(files, file => file.Key.EndsWith("ConfigDataController.cs"));
Assert.Contains(files, file => file.Key.EndsWith("ConfigServerData.cs"));
//string startUpContents = files.Find(x => x.Key == "Startup.cs").Value;
//Assert.Contains("using Steeltoe.CloudFoundry.Connector.PostgreSql;", startUpContents);
//Assert.Contains("services.AddPostgresConnection(Configuration);", startUpContents);
}
[Theory]
[ClassData(typeof(AllImplementationsAndTemplates))]
public async Task CreateTemplate_postgresEFCore(ITemplateService templateService, string templateName, TemplateVersion version)
{
var files = await templateService.GenerateProjectFiles(new Initializr.Models.GeneratorModel()
var files = await templateService.GenerateProjectFiles(new Models.GeneratorModel()
{
Dependencies = "PostgresEFCore",
TemplateShortName = templateName,
@ -215,7 +239,7 @@ namespace Steeltoe.Initializr.Tests
[ClassData(typeof(AllImplementationsAndTemplates))]
public async Task CreateTemplate_RabbitMQ(ITemplateService templateService, string templateName, TemplateVersion version)
{
var files = await templateService.GenerateProjectFiles(new Initializr.Models.GeneratorModel()
var files = await templateService.GenerateProjectFiles(new Models.GeneratorModel()
{
Dependencies = "RabbitMQ",
TemplateShortName = templateName,
@ -232,7 +256,7 @@ namespace Steeltoe.Initializr.Tests
[ClassData(typeof(AllImplementationsAndTemplates))]
public async Task CreateTemplate_Redis(ITemplateService templateService, string templateName, TemplateVersion version)
{
var files = await templateService.GenerateProjectFiles(new Initializr.Models.GeneratorModel()
var files = await templateService.GenerateProjectFiles(new Models.GeneratorModel()
{
Dependencies = "Redis",
TemplateShortName = templateName,
@ -248,7 +272,7 @@ namespace Steeltoe.Initializr.Tests
[ClassData(typeof(AllImplementationsAndTemplates))]
public async Task CreateTemplate_MongoDB(ITemplateService templateService, string templateName, TemplateVersion version)
{
var files = await templateService.GenerateProjectFiles(new Initializr.Models.GeneratorModel()
var files = await templateService.GenerateProjectFiles(new Models.GeneratorModel()
{
Dependencies = "MongoDB",
TemplateShortName = templateName,
@ -264,7 +288,7 @@ namespace Steeltoe.Initializr.Tests
[ClassData(typeof(AllImplementationsAndTemplates))]
public async Task CreateTemplate_OauthConnector(ITemplateService templateService, string templateName, TemplateVersion version)
{
var files = await templateService.GenerateProjectFiles(new Initializr.Models.GeneratorModel()
var files = await templateService.GenerateProjectFiles(new Models.GeneratorModel()
{
Dependencies = "OAuthConnector",
TemplateShortName = templateName,
@ -282,7 +306,7 @@ namespace Steeltoe.Initializr.Tests
{
var steeltoeVersion = "2.3.0";
var files = await templateService.GenerateProjectFiles(new Initializr.Models.GeneratorModel()
var files = await templateService.GenerateProjectFiles(new Models.GeneratorModel()
{
Dependencies = "SQLServer",
ProjectName = "testProject",
@ -359,7 +383,7 @@ namespace Steeltoe.Initializr.Tests
[ClassData(typeof(AllImplementationsAndTemplates))]
public async Task CreateTemplate_actuators_v22(ITemplateService templateService, string templateName, TemplateVersion version)
{
var files = await templateService.GenerateProjectFiles(new Initializr.Models.GeneratorModel()
var files = await templateService.GenerateProjectFiles(new Models.GeneratorModel()
{
Dependencies = "Actuators",
SteeltoeVersion = "2.2.0",
@ -422,6 +446,7 @@ namespace Steeltoe.Initializr.Tests
var startUpContents = files.Find(x => x.Key == "Startup.cs").Value;
Assert.DoesNotContain(files, file => file.Key.StartsWith("Models"));
Assert.DoesNotContain(files, file => file.Key.EndsWith("ConfigDataController.cs"));
Assert.DoesNotContain("AddCloudFoundryActuators", startUpContents);
var dockerFile = files.Find(x => x.Key == "Dockerfile").Value;
Assert.NotNull(dockerFile);
@ -449,7 +474,7 @@ namespace Steeltoe.Initializr.Tests
return;
}
var files = await templateService.GenerateProjectFiles(new Initializr.Models.GeneratorModel()
var files = await templateService.GenerateProjectFiles(new Models.GeneratorModel()
{
Dependencies = "Actuators,SQLServer",
TemplateShortName = templateName,
@ -473,7 +498,7 @@ namespace Steeltoe.Initializr.Tests
return;
}
var files = await templateService.GenerateProjectFiles(new Initializr.Models.GeneratorModel()
var files = await templateService.GenerateProjectFiles(new Models.GeneratorModel()
{
TemplateShortName = templateName,
ProjectName = "Foo.Bar",

23
tests/TestHelper.cs Normal file
Просмотреть файл

@ -0,0 +1,23 @@
using Microsoft.Extensions.Configuration;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Steeltoe.Initializr.Tests
{
public class TestHelper
{
public static IConfigurationRoot GetConfiguration()
{
var settings = new Dictionary<string, string>()
{
["FriendlyNames:CloudFoundry"] = "Cloud Foundry",
};
return new ConfigurationBuilder()
.AddInMemoryCollection(settings)
.Build();
}
}
}

Просмотреть файл

@ -1,20 +0,0 @@
// Copyright 2017 the original author or authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
namespace Steeltoe.Initializr.Tests
{
public class TestHelpers
{
}
}