Browse Source

m8s comands working in tye (#21)

* m8s comands working in tye

* fix styles
pull/22/head
Ryan Nowak 7 years ago
committed by GitHub
parent
commit
b4b9445f17
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 34
      samples/single-project/single-project.sln
  2. 26
      samples/single-project/test-project/Program.cs
  3. 27
      samples/single-project/test-project/Properties/launchSettings.json
  4. 40
      samples/single-project/test-project/Startup.cs
  5. 9
      samples/single-project/test-project/appsettings.Development.json
  6. 10
      samples/single-project/test-project/appsettings.json
  7. 8
      samples/single-project/test-project/test-project.csproj
  8. 2
      src/micronetes/Micronetes.Hosting.Runtime/Micronetes.Hosting.Runtime.csproj
  9. 4
      src/micronetes/Micronetes.Hosting/Micronetes.Hosting.csproj
  10. 3
      src/micronetes/Micronetes.Hosting/Model/Application.cs
  11. 259
      src/micronetes/m8s/Program.cs
  12. 7
      src/micronetes/m8s/Properties/launchSettings.json
  13. 20
      src/micronetes/m8s/m8s.csproj
  14. 23
      src/tye/NameSanitizer.cs
  15. 153
      src/tye/Program.InitCommand.cs
  16. 72
      src/tye/Program.RunCommand.cs
  17. 3
      src/tye/Program.cs
  18. 5
      src/tye/tye.csproj
  19. 15
      tye.sln

34
samples/single-project/single-project.sln

@ -0,0 +1,34 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26124.0
MinimumVisualStudioVersion = 15.0.26124.0
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "test-project", "test-project\test-project.csproj", "{7D3606B2-7B8E-4ABB-BE0A-E0B18285D8F5}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{7D3606B2-7B8E-4ABB-BE0A-E0B18285D8F5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7D3606B2-7B8E-4ABB-BE0A-E0B18285D8F5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7D3606B2-7B8E-4ABB-BE0A-E0B18285D8F5}.Debug|x64.ActiveCfg = Debug|Any CPU
{7D3606B2-7B8E-4ABB-BE0A-E0B18285D8F5}.Debug|x64.Build.0 = Debug|Any CPU
{7D3606B2-7B8E-4ABB-BE0A-E0B18285D8F5}.Debug|x86.ActiveCfg = Debug|Any CPU
{7D3606B2-7B8E-4ABB-BE0A-E0B18285D8F5}.Debug|x86.Build.0 = Debug|Any CPU
{7D3606B2-7B8E-4ABB-BE0A-E0B18285D8F5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7D3606B2-7B8E-4ABB-BE0A-E0B18285D8F5}.Release|Any CPU.Build.0 = Release|Any CPU
{7D3606B2-7B8E-4ABB-BE0A-E0B18285D8F5}.Release|x64.ActiveCfg = Release|Any CPU
{7D3606B2-7B8E-4ABB-BE0A-E0B18285D8F5}.Release|x64.Build.0 = Release|Any CPU
{7D3606B2-7B8E-4ABB-BE0A-E0B18285D8F5}.Release|x86.ActiveCfg = Release|Any CPU
{7D3606B2-7B8E-4ABB-BE0A-E0B18285D8F5}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
EndGlobal

26
samples/single-project/test-project/Program.cs

@ -0,0 +1,26 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
namespace test_project
{
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
}

27
samples/single-project/test-project/Properties/launchSettings.json

@ -0,0 +1,27 @@
{
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:18482",
"sslPort": 44344
}
},
"profiles": {
"IIS Express": {
"commandName": "IISExpress",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
},
"test_project": {
"commandName": "Project",
"launchBrowser": true,
"applicationUrl": "https://localhost:5001;http://localhost:5000",
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
}
}
}
}

40
samples/single-project/test-project/Startup.cs

@ -0,0 +1,40 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
namespace test_project
{
public class Startup
{
// This method gets called by the runtime. Use this method to add services to the container.
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
public void ConfigureServices(IServiceCollection services)
{
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapGet("/", async context =>
{
await context.Response.WriteAsync("Hello World!");
});
});
}
}
}

9
samples/single-project/test-project/appsettings.Development.json

@ -0,0 +1,9 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
}
}

10
samples/single-project/test-project/appsettings.json

@ -0,0 +1,10 @@
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"AllowedHosts": "*"
}

8
samples/single-project/test-project/test-project.csproj

@ -0,0 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<RootNamespace>test_project</RootNamespace>
</PropertyGroup>
</Project>

2
src/micronetes/Micronetes.Hosting.Runtime/Micronetes.Hosting.Runtime.csproj

@ -2,7 +2,7 @@
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
<Description>Runtime helpers for m8s host platform</Description>
<Description>Runtime helpers for tye host platform</Description>
<Nullable>disable</Nullable>
</PropertyGroup>

4
src/micronetes/Micronetes.Hosting/Micronetes.Hosting.csproj

@ -13,6 +13,10 @@
<EmbeddedResource Include="wwwroot\**" />
</ItemGroup>
<ItemGroup>
<Compile Include="..\..\tye\NameSanitizer.cs" Link="NameSanitizer.cs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Bedrock.Framework" Version="0.1.38-alpha.gd25d5b37ad" />
<PackageReference Include="FeatherHttp" Version="0.1.42-alpha.gf06a8747e7" />

3
src/micronetes/Micronetes.Hosting/Model/Application.cs

@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.IO;
using System.Text.Json;
using Microsoft.Build.Construction;
using Tye;
using YamlDotNet.Serialization;
using YamlDotNet.Serialization.NamingConventions;
@ -250,7 +251,7 @@ namespace Micronetes.Hosting.Model
// If there's a launchSettings.json, then use it to get addresses
var root = JsonSerializer.Deserialize<JsonElement>(File.ReadAllText(launchSettingsPath));
var key = Path.GetFileNameWithoutExtension(projectFilePath);
var key = NameSanitizer.SanitizeToIdentifier(Path.GetFileNameWithoutExtension(projectFilePath));
var profiles = root.GetProperty("profiles");
return profiles.TryGetProperty(key, out projectSettings);
}

259
src/micronetes/m8s/Program.cs

@ -1,259 +0,0 @@
using System;
using System.CommandLine;
using System.CommandLine.Builder;
using System.CommandLine.Invocation;
using System.CommandLine.IO;
using System.CommandLine.Parsing;
using System.CommandLine.Rendering;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using Micronetes.Hosting;
using Micronetes.Hosting.Model;
using YamlDotNet.Serialization;
using YamlDotNet.Serialization.NamingConventions;
namespace Micronetes.Host
{
class Program
{
static async Task<int> Main(string[] args)
{
var command = new RootCommand();
command.Add(RunCommand(args));
command.Add(NewCommand());
command.Description = "Process manager and orchestrator for microservices.";
var builder = new CommandLineBuilder(command);
builder.UseHelp();
builder.UseVersionOption();
builder.UseDebugDirective();
builder.UseParseErrorReporting();
builder.ParseResponseFileAs(ResponseFileHandling.ParseArgsAsSpaceSeparated);
builder.UsePrefixes(new[] { "-", "--", }); // disable garbage windows conventions
builder.CancelOnProcessTermination();
builder.UseExceptionHandler(HandleException);
// Allow fancy drawing.
builder.UseAnsiTerminalWhenAvailable();
var parser = builder.Build();
return await parser.InvokeAsync(args);
}
private static Command NewCommand()
{
var command = new Command("new", "create a yaml manifest")
{
};
var argument = new Argument("path")
{
Description = "A solution or project file to generate a yaml manifest from",
Arity = ArgumentArity.ZeroOrOne
};
command.AddArgument(argument);
command.Handler = CommandHandler.Create<IConsole, string>((console, path) =>
{
if (File.Exists("m8s.yaml"))
{
console.Out.WriteLine("\"m8s.yaml\" already exists.");
return;
}
var template = @"- name: app
# project: app.csproj # msbuild project path (relative to this file)
# executable: app.exe # path to an executable (relative to this file)
# args: --arg1=3 # arguments to pass to the process
# replicas: 5 # number of times to launch the application
# env: # array of environment variables
# - name: key
# value: value
# bindings: # optional array of bindings (ports, connection strings)
# - port: 8080 # number port of the binding
";
try
{
if (!string.IsNullOrEmpty(path))
{
var application = ResolveApplication(path);
var serializer = new SerializerBuilder()
.WithNamingConvention(CamelCaseNamingConvention.Instance)
.ConfigureDefaultValuesHandling(DefaultValuesHandling.OmitDefaults)
.Build();
var extension = Path.GetExtension(application.Source).ToLowerInvariant();
var directory = Path.GetDirectoryName(application.Source);
var descriptions = application.Services.Select(s => s.Value.Description).ToList();
// Clear all bindings if any for solutions and project files
if (extension == ".sln" || extension == ".csproj" || extension == ".fsproj")
{
foreach (var d in descriptions)
{
d.Bindings = null;
d.Replicas = null;
d.Build = null;
d.Configuration = null;
d.Project = d.Project.Substring(directory.Length).TrimStart(Path.DirectorySeparatorChar);
}
}
template = serializer.Serialize(descriptions);
}
}
catch (FileNotFoundException)
{
// No file found, just generate a new one
}
File.WriteAllText("m8s.yaml", template);
console.Out.WriteLine("Created \"m8s.yaml\"");
});
return command;
}
private static Command RunCommand(string[] args)
{
var command = new Command("run", "run the application")
{
};
var argument = new Argument("path")
{
Description = "A file or directory to execute. Supports a project files, solution files or a yaml manifest.",
Arity = ArgumentArity.ZeroOrOne
};
// TODO: We'll need to support a --build-args
command.AddOption(new Option("--no-build")
{
Description = "Do not build project files before running.",
Required = false
});
command.AddOption(new Option("--port")
{
Description = "The port to run control plane on.",
Argument = new Argument<int>("port"),
Required = false
});
command.AddOption(new Option("--logs")
{
Description = "Write structured application logs to the specified log providers. Supported providers are console, elastic (Elasticsearch), ai (ApplicationInsights), seq.",
Argument = new Argument<string>("logs"),
Required = false
});
command.AddOption(new Option("--dtrace")
{
Description = "Write distributed traces to the specified providers. Supported providers are zipkin.",
Argument = new Argument<string>("logs"),
Required = false
});
command.AddOption(new Option("--debug")
{
Description = "Wait for debugger attach in all services.",
Required = false
});
command.AddArgument(argument);
command.Handler = CommandHandler.Create<IConsole, string>((console, path) =>
{
Application app = ResolveApplication(path);
return MicronetesHost.RunAsync(app, args);
});
return command;
}
private static Application ResolveApplication(string path)
{
if (string.IsNullOrEmpty(path))
{
path = ResolveFileFromDirectory(Directory.GetCurrentDirectory());
}
else if (Directory.Exists(path))
{
path = ResolveFileFromDirectory(Path.GetFullPath(path));
}
if (!File.Exists(path))
{
throw new FileNotFoundException($"{path} does not exist");
}
switch (Path.GetExtension(path).ToLower())
{
case ".yaml":
case ".yml":
return Application.FromYaml(path);
case ".csproj":
case ".fsproj":
return Application.FromProject(path);
case ".sln":
return Application.FromSolution(path);
default:
throw new NotSupportedException($"{path} not supported");
}
}
private static string ResolveFileFromDirectory(string basePath)
{
var formats = new[] { "m8s.yaml", "m8s.yml", "*.csproj", "*.fsproj", "*.sln" };
foreach (var format in formats)
{
var files = Directory.GetFiles(basePath, format);
if (files.Length == 0)
{
continue;
}
if (files.Length > 1)
{
throw new InvalidOperationException($"Ambiguous match found {string.Join(", ", files.Select(Path.GetFileName))}");
}
return files[0];
}
throw new InvalidOperationException($"None of the supported files were found (m8s.yaml, .csproj, .fsproj, .sln)");
}
private static void HandleException(Exception exception, InvocationContext context)
{
// context.Console.ResetTerminalForegroundColor();
// context.Console.SetTerminalForegroundColor(ConsoleColor.Red);
if (exception is OperationCanceledException)
{
context.Console.Error.WriteLine("operation canceled.");
}
else if (exception is TargetInvocationException tae)
{
context.Console.Error.WriteLine(tae.InnerException.Message);
}
else
{
context.Console.Error.WriteLine("unhandled exception: ");
context.Console.Error.WriteLine(exception.ToString());
}
// context.Console.ResetTerminalForegroundColor();
context.ResultCode = 1;
}
}
}

7
src/micronetes/m8s/Properties/launchSettings.json

@ -1,7 +0,0 @@
{
"profiles": {
"dotnet-micronetes": {
"commandName": "Project"
}
}
}

20
src/micronetes/m8s/m8s.csproj

@ -1,20 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
<PackAsTool>true</PackAsTool>
<RootNamespace>Micronetes.Host</RootNamespace>
<AssemblyName>m8s</AssemblyName>
<ToolCommandName>m8s</ToolCommandName>
<Description>Local orchestrator for microservices.</Description>
<Nullable>disable</Nullable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Micronetes.Hosting\Micronetes.Hosting.csproj" />
<PackageReference Include="System.CommandLine" Version="2.0.0-beta1.20071.2" />
<PackageReference Include="System.Commandline.Rendering" Version="0.3.0-alpha.20070.2" />
</ItemGroup>
</Project>

23
src/tye/NameSanitizer.cs

@ -0,0 +1,23 @@
using System;
namespace Tye
{
internal static class NameSanitizer
{
// Converts an arbitrary string into something usable as a C# identifier.
//
// For instance the project file might be `test-project.csproj` but `test-project` is
// not what will appear in `launchSettings.json`. We need to convert to
// `test_project`
public static string SanitizeToIdentifier(string name)
{
if (name is null)
{
throw new ArgumentNullException(nameof(name));
}
// This is not perfect. For now it just handles cases we've encountered.
return name.Replace("-", "_");
}
}
}

153
src/tye/Program.InitCommand.cs

@ -0,0 +1,153 @@
using System;
using System.CommandLine;
using System.CommandLine.Invocation;
using System.CommandLine.IO;
using System.IO;
using System.Linq;
using Micronetes.Hosting.Model;
using YamlDotNet.Serialization;
using YamlDotNet.Serialization.NamingConventions;
namespace Tye
{
static partial class Program
{
private static Command CreateInitCommand()
{
var command = new Command("init", "create a yaml manifest")
{
};
var argument = new Argument("path")
{
Description = "A solution or project file to generate a yaml manifest from",
Arity = ArgumentArity.ZeroOrOne
};
command.AddArgument(argument);
command.Handler = CommandHandler.Create<IConsole, string>((console, path) =>
{
if (File.Exists("tye.yaml"))
{
console.Out.WriteLine("\"tye.yaml\" already exists.");
return;
}
var template = @"- name: app
# project: app.csproj # msbuild project path (relative to this file)
# executable: app.exe # path to an executable (relative to this file)
# args: --arg1=3 # arguments to pass to the process
# replicas: 5 # number of times to launch the application
# env: # array of environment variables
# - name: key
# value: value
# bindings: # optional array of bindings (ports, connection strings)
# - port: 8080 # number port of the binding
";
try
{
var application = ResolveApplication(path);
if (application is object)
{
var serializer = new SerializerBuilder()
.WithNamingConvention(CamelCaseNamingConvention.Instance)
.ConfigureDefaultValuesHandling(DefaultValuesHandling.OmitDefaults)
.Build();
var extension = Path.GetExtension(application.Source).ToLowerInvariant();
var directory = Path.GetDirectoryName(application.Source);
var descriptions = application.Services.Select(s => s.Value.Description).ToList();
// Clear all bindings if any for solutions and project files
if (extension == ".sln" || extension == ".csproj" || extension == ".fsproj")
{
foreach (var d in descriptions)
{
d.Bindings = null;
d.Replicas = null;
d.Build = null;
d.Configuration = null;
d.Project = d.Project.Substring(directory.Length).TrimStart(Path.DirectorySeparatorChar);
}
}
template = serializer.Serialize(descriptions);
}
}
catch (FileNotFoundException)
{
// No file found, just generate a new one
}
File.WriteAllText("tye.yaml", template);
console.Out.WriteLine("Created \"tye.yaml\"");
});
return command;
}
private static Application? ResolveApplication(string? path)
{
if (string.IsNullOrEmpty(path))
{
path = ResolveFileFromDirectory(Directory.GetCurrentDirectory());
}
else if (Directory.Exists(path))
{
path = ResolveFileFromDirectory(Path.GetFullPath(path));
}
if (path == null)
{
return null;
}
if (!File.Exists(path))
{
throw new FileNotFoundException($"{path} does not exist");
}
switch (Path.GetExtension(path).ToLower())
{
case ".yaml":
case ".yml":
return Application.FromYaml(path);
case ".csproj":
case ".fsproj":
return Application.FromProject(path);
case ".sln":
return Application.FromSolution(path);
default:
throw new NotSupportedException($"{path} not supported");
}
}
private static string? ResolveFileFromDirectory(string basePath)
{
var formats = new[] { "tye.yaml", "tye.yml", "*.csproj", "*.fsproj", "*.sln" };
foreach (var format in formats)
{
var files = Directory.GetFiles(basePath, format);
if (files.Length == 0)
{
continue;
}
if (files.Length > 1)
{
throw new InvalidOperationException($"Ambiguous match found {string.Join(", ", files.Select(Path.GetFileName))}");
}
return files[0];
}
return null;
}
}
}

72
src/tye/Program.RunCommand.cs

@ -0,0 +1,72 @@
using System;
using System.CommandLine;
using System.CommandLine.Invocation;
using Micronetes.Hosting;
namespace Tye
{
static partial class Program
{
private static Command CreateRunCommand(string[] args)
{
var command = new Command("run", "run the application")
{
};
var argument = new Argument("path")
{
Description = "A file or directory to execute. Supports a project files, solution files or a yaml manifest.",
Arity = ArgumentArity.ZeroOrOne
};
// TODO: We'll need to support a --build-args
command.AddOption(new Option("--no-build")
{
Description = "Do not build project files before running.",
Required = false
});
command.AddOption(new Option("--port")
{
Description = "The port to run control plane on.",
Argument = new Argument<int>("port"),
Required = false
});
command.AddOption(new Option("--logs")
{
Description = "Write structured application logs to the specified log providers. Supported providers are console, elastic (Elasticsearch), ai (ApplicationInsights), seq.",
Argument = new Argument<string>("logs"),
Required = false
});
command.AddOption(new Option("--dtrace")
{
Description = "Write distributed traces to the specified providers. Supported providers are zipkin.",
Argument = new Argument<string>("logs"),
Required = false
});
command.AddOption(new Option("--debug")
{
Description = "Wait for debugger attach in all services.",
Required = false
});
command.AddArgument(argument);
command.Handler = CommandHandler.Create<IConsole, string>((console, path) =>
{
var application = ResolveApplication(path);
if (application is null)
{
throw new CommandException($"None of the supported files were found (tye.yaml, .csproj, .fsproj, .sln)");
}
return MicronetesHost.RunAsync(application, args);
});
return command;
}
}
}

3
src/tye/Program.cs

@ -18,6 +18,9 @@ namespace Tye
Description = "Developer tools and publishing for microservices.",
};
command.AddCommand(CreateInitCommand());
command.AddCommand(CreateRunCommand(args));
// Show commandline help unless a subcommand was used.
command.Handler = CommandHandler.Create<IHelpBuilder>(help =>
{

5
src/tye/tye.csproj

@ -9,8 +9,13 @@
<PackAsTool>true</PackAsTool>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\micronetes\Micronetes.Hosting\Micronetes.Hosting.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="System.CommandLine" Version="2.0.0-beta1.20104.2" />
<PackageReference Include="YamlDotNet" Version="8.0.0" />
</ItemGroup>
</Project>

15
tye.sln

@ -25,8 +25,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Micronetes.Hosting.Diagnost
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Micronetes.Hosting.Runtime", "src\micronetes\Micronetes.Hosting.Runtime\Micronetes.Hosting.Runtime.csproj", "{34719884-1338-4965-BA2A-F98DB03733C2}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "m8s", "src\micronetes\m8s\m8s.csproj", "{01C77687-2E5E-4DB3-B88C-218FC706DC7D}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -124,18 +122,6 @@ Global
{34719884-1338-4965-BA2A-F98DB03733C2}.Release|x64.Build.0 = Release|Any CPU
{34719884-1338-4965-BA2A-F98DB03733C2}.Release|x86.ActiveCfg = Release|Any CPU
{34719884-1338-4965-BA2A-F98DB03733C2}.Release|x86.Build.0 = Release|Any CPU
{01C77687-2E5E-4DB3-B88C-218FC706DC7D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{01C77687-2E5E-4DB3-B88C-218FC706DC7D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{01C77687-2E5E-4DB3-B88C-218FC706DC7D}.Debug|x64.ActiveCfg = Debug|Any CPU
{01C77687-2E5E-4DB3-B88C-218FC706DC7D}.Debug|x64.Build.0 = Debug|Any CPU
{01C77687-2E5E-4DB3-B88C-218FC706DC7D}.Debug|x86.ActiveCfg = Debug|Any CPU
{01C77687-2E5E-4DB3-B88C-218FC706DC7D}.Debug|x86.Build.0 = Debug|Any CPU
{01C77687-2E5E-4DB3-B88C-218FC706DC7D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{01C77687-2E5E-4DB3-B88C-218FC706DC7D}.Release|Any CPU.Build.0 = Release|Any CPU
{01C77687-2E5E-4DB3-B88C-218FC706DC7D}.Release|x64.ActiveCfg = Release|Any CPU
{01C77687-2E5E-4DB3-B88C-218FC706DC7D}.Release|x64.Build.0 = Release|Any CPU
{01C77687-2E5E-4DB3-B88C-218FC706DC7D}.Release|x86.ActiveCfg = Release|Any CPU
{01C77687-2E5E-4DB3-B88C-218FC706DC7D}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
{9BFE4070-D6D8-41F8-B92E-F85C3DCD7AB8} = {8C662D59-A3CB-466F-8E85-A8E6BA5E7601}
@ -147,6 +133,5 @@ Global
{0F4F5A86-DD27-4AF9-BF97-221EAD5040E7} = {B2C364E4-969E-4770-BF5F-BE65D292F70A}
{CEBFC149-8162-4A0A-9AD4-40498B9172CD} = {B2C364E4-969E-4770-BF5F-BE65D292F70A}
{34719884-1338-4965-BA2A-F98DB03733C2} = {B2C364E4-969E-4770-BF5F-BE65D292F70A}
{01C77687-2E5E-4DB3-B88C-218FC706DC7D} = {B2C364E4-969E-4770-BF5F-BE65D292F70A}
EndGlobalSection
EndGlobal

Loading…
Cancel
Save