Initial check in of Cloudfoundry config extension provider

Added the projects to solution also
This commit is contained in:
Dave Tillman 2016-01-06 15:51:59 -08:00
Родитель 45cdb279b2
Коммит 09262390bf
11 изменённых файлов: 438 добавлений и 0 удалений

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

@ -18,6 +18,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Spring.Extensions.Configuration.Server.IntegrationTest", "test\Spring.Extensions.Configuration.Server.IntegrationTest\Spring.Extensions.Configuration.Server.IntegrationTest.xproj", "{8D43B1B0-0C20-4AA5-B510-332E1190D0C3}"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Spring.Extensions.Configuration.Cloudfoundry", "src\Spring.Extensions.Configuration.Cloudfoundry\Spring.Extensions.Configuration.Cloudfoundry.xproj", "{4A9D10C9-D365-41DD-9870-9D846A3D9EB1}"
EndProject
Project("{8BB2217D-0F2D-49D1-97BC-3654ED321F3B}") = "Spring.Extensions.Configuration.Cloudfoundry.Test", "test\Spring.Extensions.Configuration.Cloudfoundry.Test\Spring.Extensions.Configuration.Cloudfoundry.Test.xproj", "{9F29BED6-ECE3-42A2-8C57-C1A6831B9CF1}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -36,6 +40,14 @@ Global
{8D43B1B0-0C20-4AA5-B510-332E1190D0C3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{8D43B1B0-0C20-4AA5-B510-332E1190D0C3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{8D43B1B0-0C20-4AA5-B510-332E1190D0C3}.Release|Any CPU.Build.0 = Release|Any CPU
{4A9D10C9-D365-41DD-9870-9D846A3D9EB1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4A9D10C9-D365-41DD-9870-9D846A3D9EB1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4A9D10C9-D365-41DD-9870-9D846A3D9EB1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4A9D10C9-D365-41DD-9870-9D846A3D9EB1}.Release|Any CPU.Build.0 = Release|Any CPU
{9F29BED6-ECE3-42A2-8C57-C1A6831B9CF1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{9F29BED6-ECE3-42A2-8C57-C1A6831B9CF1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{9F29BED6-ECE3-42A2-8C57-C1A6831B9CF1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{9F29BED6-ECE3-42A2-8C57-C1A6831B9CF1}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -44,5 +56,7 @@ Global
{D06283B3-995E-4AC2-B45F-DF6A6C377644} = {68054802-1B15-4550-8ED5-1899E5EA3DD9}
{ECCB52BE-A124-4213-95A3-0C4842AA55A1} = {51AE05BE-C7D3-48A4-9B30-4D7B90283CD8}
{8D43B1B0-0C20-4AA5-B510-332E1190D0C3} = {51AE05BE-C7D3-48A4-9B30-4D7B90283CD8}
{4A9D10C9-D365-41DD-9870-9D846A3D9EB1} = {68054802-1B15-4550-8ED5-1899E5EA3DD9}
{9F29BED6-ECE3-42A2-8C57-C1A6831B9CF1} = {51AE05BE-C7D3-48A4-9B30-4D7B90283CD8}
EndGlobalSection
EndGlobal

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

@ -0,0 +1,104 @@
using Microsoft.Extensions.Configuration;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.Configuration.EnvironmentVariables;
using System.Collections;
using Microsoft.Extensions.Configuration.Json;
using System.IO;
namespace Spring.Extensions.Configuration.Cloudfoundry
{
public class CloudfoundryConfigurationProvider : ConfigurationProvider
{
private const string VCAP_PREFIX = "VCAP_";
private const string APPLICATION = "APPLICATION";
private const string SERVICES = "SERVICES";
public CloudfoundryConfigurationProvider()
{
}
public override void Load()
{
var builder = new ConfigurationBuilder();
builder.Add(new EnvironmentVariablesConfigurationProvider(VCAP_PREFIX));
var vcap = builder.Build();
Process(vcap);
}
private void Process(IConfigurationRoot vcap)
{
string appJson = vcap[APPLICATION];
if (!string.IsNullOrEmpty(appJson))
{
// TODO: Hack in order to use asp.net json config provider
// Need to write parser
var path = CreateTempFile(appJson);
ConfigurationBuilder builder = new ConfigurationBuilder();
builder.AddJsonFile(path);
var applicationData = builder.Build();
if (applicationData != null)
{
LoadData("vcap:application", applicationData.GetChildren());
}
}
string appServicesJson = vcap[SERVICES];
if (!string.IsNullOrEmpty(appServicesJson))
{
// TODO: Hack in order to use asp.net json config provider
// Need to write parser
var path = CreateTempFile(appServicesJson);
ConfigurationBuilder builder = new ConfigurationBuilder();
builder.AddJsonFile(path);
var servicesData = builder.Build();
if (servicesData != null)
{
LoadData("vcap:services", servicesData.GetChildren());
}
}
}
internal IDictionary<string, string> Properties
{
get
{
return Data;
}
}
private void LoadData(string prefix, IEnumerable<IConfigurationSection> sections)
{
if (sections == null || sections.Count() == 0)
{
return;
}
foreach(IConfigurationSection section in sections)
{
LoadSection(prefix, section);
LoadData(prefix, section.GetChildren());
}
}
private void LoadSection(string prefix, IConfigurationSection section)
{
if (section == null)
return;
if (string.IsNullOrEmpty(section.Value))
return;
Data[prefix + Constants.KeyDelimiter + section.Path] = section.Value;
}
// TODO: Remove
private static string CreateTempFile(string contents)
{
var tempFile = Path.GetTempFileName();
File.WriteAllText(tempFile, contents);
return tempFile;
}
}
}

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

@ -0,0 +1,25 @@
using Microsoft.Extensions.Configuration;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Spring.Extensions.Configuration.Cloudfoundry
{
public static class CloudfoundryConfigurationExtensions
{
public static IConfigurationBuilder AddCloudfoundry(this IConfigurationBuilder configurationBuilder)
{
if (configurationBuilder == null)
{
throw new ArgumentNullException(nameof(configurationBuilder));
}
configurationBuilder.Add(new CloudfoundryConfigurationProvider());
return configurationBuilder;
}
}
}

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

@ -0,0 +1,25 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Spring.Extensions.Configuration.Cloudfoundry")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Spring.Extensions.Configuration.Cloudfoundry")]
[assembly: AssemblyCopyright("Copyright © 2016")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("4a9d10c9-d365-41dd-9870-9d846a3d9eb1")]
[assembly: InternalsVisibleTo("Spring.Extensions.Configuration.Cloudfoundry.Test")]

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

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.Props" Condition="'$(VSToolsPath)' != ''" />
<PropertyGroup Label="Globals">
<ProjectGuid>4a9d10c9-d365-41dd-9870-9d846a3d9eb1</ProjectGuid>
<RootNamespace>Spring.Extensions.Configuration.Cloudfoundry</RootNamespace>
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath>
<OutputPath Condition="'$(OutputPath)'=='' ">..\..\artifacts\bin\$(MSBuildProjectName)\</OutputPath>
</PropertyGroup>
<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" Condition="'$(VSToolsPath)' != ''" />
</Project>

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

@ -0,0 +1,26 @@
{
"version": "1.0.0-*",
"description": "Cloudfoundry configuration provider",
"authors": [ "dtillman" ],
"tags": [ "" ],
"projectUrl": "",
"licenseUrl": "",
"frameworks": {
"net451": {
"dependencies": {
}
},
"dnxcore50": {
"dependencies": {
}
}
},
"dependencies": {
"Microsoft.Extensions.Configuration": "1.0.0-*",
"Microsoft.Extensions.Configuration.EnvironmentVariables": "1.0.0-*",
"Microsoft.Extensions.Configuration.Json": "1.0.0-*",
"Microsoft.Extensions.Logging.Abstractions": "1.0.0-*",
"Newtonsoft.Json": "7.0.1"
}
}

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

@ -0,0 +1,44 @@
using Microsoft.Extensions.Configuration;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Xunit;
namespace Spring.Extensions.Configuration.Cloudfoundry.Test
{
public class CloudfoundryConfigurationExtensionsTest
{
[Fact]
public void AddConfigService_ThrowsIfConfigBuilderNull()
{
// Arrange
IConfigurationBuilder configurationBuilder = null;
// Act and Assert
var ex = Assert.Throws<ArgumentNullException>(() => CloudfoundryConfigurationExtensions.AddCloudfoundry(configurationBuilder));
Assert.Contains(nameof(configurationBuilder), ex.Message);
}
[Fact]
public void AddConfigService_AddsConfigServerProviderToProvidersList()
{
// Arrange
var configurationBuilder = new ConfigurationBuilder();
// Act and Assert
configurationBuilder.AddCloudfoundry();
CloudfoundryConfigurationProvider cloudProvider = null;
foreach (IConfigurationProvider provider in configurationBuilder.Providers)
{
cloudProvider = provider as CloudfoundryConfigurationProvider;
if (cloudProvider != null)
break;
}
Assert.NotNull(cloudProvider);
}
}
}

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

@ -0,0 +1,105 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Xunit;
using Spring.Extensions.Configuration.Cloudfoundry;
namespace Spring.Extensions.Configuration.Cloudfoundry.Test
{
public class CloudfoundryConfigurationProviderTest
{
public CloudfoundryConfigurationProviderTest()
{
}
[Fact]
public void LoadVCAP_APPLICATION_ChangesDataDictionary()
{
// Arrange
var environment = @"
{
'application_id': 'fa05c1a9-0fc1-4fbd-bae1-139850dec7a3',
'application_name': 'my-app',
'application_uris': [
'my-app.10.244.0.34.xip.io'
],
'application_version': 'fb8fbcc6-8d58-479e-bcc7-3b4ce5a7f0ca',
'limits': {
'disk': 1024,
'fds': 16384,
'mem': 256
},
'name': 'my-app',
'space_id': '06450c72-4669-4dc6-8096-45f9777db68a',
'space_name': 'my-space',
'uris': [
'my-app.10.244.0.34.xip.io',
'my-app2.10.244.0.34.xip.io'
],
'users': null,
'version': 'fb8fbcc6-8d58-479e-bcc7-3b4ce5a7f0ca'
}";
Environment.SetEnvironmentVariable("VCAP_APPLICATION", environment);
var provider = new CloudfoundryConfigurationProvider();
// Act and Assert
provider.Load();
IDictionary<string, string> dict = provider.Properties;
Assert.Equal("fa05c1a9-0fc1-4fbd-bae1-139850dec7a3", dict["vcap:application:application_id"]);
Assert.Equal("1024", dict["vcap:application:limits:disk"]);
Assert.Equal("my-app.10.244.0.34.xip.io", dict["vcap:application:uris:0"]);
Assert.Equal("my-app2.10.244.0.34.xip.io", dict["vcap:application:uris:1"]);
}
[Fact]
public void LoadVCAP_SERVICES_ChangesDataDictionary()
{
var environment = @"
{
'elephantsql': [
{
'name': 'elephantsql-c6c60',
'label': 'elephantsql',
'tags': [
'postgres',
'postgresql',
'relational'
],
'plan': 'turtle',
'credentials': {
'uri': 'postgres://seilbmbd:ABcdEF@babar.elephantsql.com:5432/seilbmbd'
}
}
],
'sendgrid': [
{
'name': 'mysendgrid',
'label': 'sendgrid',
'tags': [
'smtp'
],
'plan': 'free',
'credentials': {
'hostname': 'smtp.sendgrid.net',
'username': 'QvsXMbJ3rK',
'password': 'HCHMOYluTv'
}
}
]
}";
Environment.SetEnvironmentVariable("VCAP_SERVICES", environment);
var provider = new CloudfoundryConfigurationProvider();
// Act and Assert
provider.Load();
IDictionary<string, string> dict = provider.Properties;
Assert.Equal("elephantsql-c6c60", dict["vcap:services:elephantsql:0:name"]);
//Assert.Equal("1024", dict["vcap:application:limits:disk"]);
//Assert.Equal("my-app.10.244.0.34.xip.io", dict["vcap:application:uris:0"]);
//Assert.Equal("my-app2.10.244.0.34.xip.io", dict["vcap:application:uris:1"]);
}
}
}

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

@ -0,0 +1,23 @@
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Spring.Extensions.Configuration.Cloudfoundry.Test")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Spring.Extensions.Configuration.Cloudfoundry.Test")]
[assembly: AssemblyCopyright("Copyright © 2016")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("9f29bed6-ece3-42a2-8c57-c1a6831b9cf1")]

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

@ -0,0 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">14.0</VisualStudioVersion>
<VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
</PropertyGroup>
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.Props" Condition="'$(VSToolsPath)' != ''" />
<PropertyGroup Label="Globals">
<ProjectGuid>9f29bed6-ece3-42a2-8c57-c1a6831b9cf1</ProjectGuid>
<RootNamespace>Spring.Extensions.Configuration.Cloudfoundry.Test</RootNamespace>
<BaseIntermediateOutputPath Condition="'$(BaseIntermediateOutputPath)'=='' ">..\..\artifacts\obj\$(MSBuildProjectName)</BaseIntermediateOutputPath>
<OutputPath Condition="'$(OutputPath)'=='' ">..\..\artifacts\bin\$(MSBuildProjectName)\</OutputPath>
</PropertyGroup>
<PropertyGroup>
<SchemaVersion>2.0</SchemaVersion>
</PropertyGroup>
<ItemGroup>
<Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
</ItemGroup>
<Import Project="$(VSToolsPath)\DNX\Microsoft.DNX.targets" Condition="'$(VSToolsPath)' != ''" />
</Project>

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

@ -0,0 +1,31 @@
{
"version": "1.0.0-*",
"description": "Unit test project for Spring.Extensions.Configuration.Cloudfoundry",
"authors": [ "dtillman" ],
"tags": [ "" ],
"projectUrl": "",
"licenseUrl": "",
"frameworks": {
"dnx451": { },
"dnxcore50": {
"dependencies": {
}
}
},
"dependencies": {
"Microsoft.AspNet.Hosting": "1.0.0-*",
"Microsoft.AspNet.Http.Abstractions": "1.0.0-*",
"Microsoft.AspNet.TestHost": "1.0.0-*",
"Microsoft.Extensions.Configuration": "1.0.0-*",
"Spring.Extensions.Configuration.Cloudfoundry": "1.0.0-*",
"xunit": "2.1.0",
"xunit.runner.dnx": "2.1.0-rc1-build204"
},
"commands": {
"test": "xunit.runner.dnx"
}
}