Browse Source

Add a library for `AddTyeSecrets`

This removes the need to copy-paste code that reads a specific directory
in Program.cs.

Updated docs/samples and tests.

We need a workaround in tests to be able to use a P2P for the library. What
I did here is the same trick we do in Razor.

- Force everyone to use an MSBuild variable to locate the library
- Set that variable in a Directory.Build.props for the normal build
- Drop a special Directory.Build.props for testing

Updates a bunch of test code to use new helper methods for copying
stuff, so we can correctly do this.
pull/290/head
Ryan Nowak 6 years ago
parent
commit
6671da72c0
  1. 31
      docs/redis.md
  2. 3
      samples/Directory.Build.props
  3. 9
      samples/multi-project/backend/Program.cs
  4. 5
      samples/multi-project/backend/backend.csproj
  5. 9
      samples/multi-project/frontend/Program.cs
  6. 5
      samples/multi-project/frontend/frontend.csproj
  7. 9
      samples/multi-project/worker/Program.cs
  8. 7
      samples/multi-project/worker/worker.csproj
  9. 15
      samples/voting/vote/Program.cs
  10. 4
      samples/voting/vote/vote.csproj
  11. 15
      samples/voting/worker/Program.cs
  12. 4
      samples/voting/worker/worker.csproj
  13. 11
      src/Microsoft.Tye.Core/KubernetesManifestGenerator.cs
  14. 11
      src/Microsoft.Tye.Extensions.Configuration/Microsoft.Tye.Extensions.Configuration.csproj
  15. 53
      src/Microsoft.Tye.Extensions.Configuration/TyeSecretsConfigurationBuilderExtensions.cs
  16. 37
      src/Microsoft.Tye.Extensions.Configuration/TyeSecretsConfigurationSource.cs
  17. 55
      test/E2ETest/TestHelpers.cs
  18. 25
      test/E2ETest/TyeBuildTests.cs
  19. 33
      test/E2ETest/TyeGenerateTests.cs
  20. 27
      test/E2ETest/TyeInitTests.cs
  21. 20
      test/E2ETest/TyePurgeTests.cs
  22. 38
      test/E2ETest/TyeRunTests.cs
  23. 6
      test/E2ETest/testassets/generate/multi-project.yaml
  24. 8
      test/E2ETest/testassets/projects/Directory.Build.props
  25. 15
      tye.sln

31
docs/redis.md

@ -134,45 +134,22 @@ We just showed how `tye` makes it easier to communicate between 2 applications r
In order to access redis we need to add some code to the `backend` project to be able to read secrets from inside the container.
First, add the `KeyPerFile` configuration provider package to the backend project using the command line.
First, add the Tye configuration provider package to the backend project using the command line.
```text
cd backend
dotnet add package Microsoft.Extensions.Configuration.KeyPerFile
dotnet add package Microsoft.Tye.Extensions.Configuration
cd ..
```
Next, add the following `using`s for the configuration provider near the top of `Program.cs`
```C#
using System.IO;
using Microsoft.Extensions.Configuration.KeyPerFile;
```
Then, add the following method to the `Program` class:
```C#
private static void AddTyeBindingSecrets(IConfigurationBuilder config)
{
if (Directory.Exists("/var/tye/bindings/"))
{
foreach (var directory in Directory.GetDirectories("/var/tye/bindings/"))
{
Console.WriteLine($"Adding config in '{directory}'.");
config.AddKeyPerFile(directory, optional: true);
}
}
}
```
Then update `CreateHostBuilder` to call the new method:
Then update `CreateHostBuilder` to create the configuration source:
```C#
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureAppConfiguration(config =>
{
AddTyeBindingSecrets(config);
config.AddTyeSecrets();
})
.ConfigureWebHostDefaults(webBuilder =>
{

3
samples/Directory.Build.props

@ -7,5 +7,8 @@
<OutputPath>$(OutDirName)$(Configuration)\</OutputPath>
<BaseIntermediateOutputPath>$([System.IO.Path]::GetFullPath('$(MSBuildProjectDirectory)\obj\'))</BaseIntermediateOutputPath>
<IntemediateOutputPath>$(BaseIntermediateOutputPath)$(Configuration)</IntemediateOutputPath>
<!-- Used for P2Ps in our samples. The tests know how to set this value so that references work. -->
<TyeLibrariesPath>$(MSBuildThisFileDirectory)\..\src\</TyeLibrariesPath>
</PropertyGroup>
</Project>

9
samples/multi-project/backend/Program.cs

@ -25,14 +25,7 @@ namespace Backend
Host.CreateDefaultBuilder(args)
.ConfigureAppConfiguration(config =>
{
if (Directory.Exists("/var/tye/bindings/"))
{
foreach (var directory in Directory.GetDirectories("/var/tye/bindings/"))
{
Console.WriteLine($"Adding config in '{directory}'.");
config.AddKeyPerFile(directory, optional: true);
}
}
config.AddTyeSecrets();
})
.ConfigureWebHostDefaults(web =>
{

5
samples/multi-project/backend/backend.csproj

@ -6,7 +6,10 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Configuration.KeyPerFile" Version="3.1.1" />
<ProjectReference Include="$(TyeLibrariesPath)\Microsoft.Tye.Extensions.Configuration\Microsoft.Tye.Extensions.Configuration.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="RabbitMQ.Client" Version="5.1.2" />
<PackageReference Include="protobuf-net.Grpc.AspNetCore" Version="1.0.21" />
</ItemGroup>

9
samples/multi-project/frontend/Program.cs

@ -26,14 +26,7 @@ namespace Frontend
Host.CreateDefaultBuilder(args)
.ConfigureAppConfiguration(config =>
{
if (Directory.Exists("/var/tye/bindings/"))
{
foreach (var directory in Directory.GetDirectories("/var/tye/bindings/"))
{
Console.WriteLine($"Adding config in '{directory}'.");
config.AddKeyPerFile(directory, optional: true);
}
}
config.AddTyeSecrets();
})
.ConfigureWebHostDefaults(webBuilder =>
{

5
samples/multi-project/frontend/frontend.csproj

@ -5,7 +5,10 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Configuration.KeyPerFile" Version="3.1.1" />
<ProjectReference Include="$(TyeLibrariesPath)\Microsoft.Tye.Extensions.Configuration\Microsoft.Tye.Extensions.Configuration.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Grpc.Net.Client" Version="2.26.0" />
<PackageReference Include="protobuf-net.Grpc" Version="1.0.21" />
</ItemGroup>

9
samples/multi-project/worker/Program.cs

@ -22,14 +22,7 @@ namespace Worker
Host.CreateDefaultBuilder(args)
.ConfigureAppConfiguration(config =>
{
if (Directory.Exists("/var/tye/bindings/"))
{
foreach (var directory in Directory.GetDirectories("/var/tye/bindings/"))
{
Console.WriteLine($"Adding config in '{directory}'.");
config.AddKeyPerFile(directory, optional: true);
}
}
config.AddTyeSecrets();
})
.ConfigureServices((hostContext, services) =>
{

7
samples/multi-project/worker/worker.csproj

@ -7,8 +7,11 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Configuration.KeyPerFile" Version="3.1.1" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="3.1.1" />
<ProjectReference Include="$(TyeLibrariesPath)\Microsoft.Tye.Extensions.Configuration\Microsoft.Tye.Extensions.Configuration.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting" Version="3.1.3" />
<PackageReference Include="RabbitMQ.Client" Version="5.1.2" />
</ItemGroup>
</Project>

15
samples/voting/vote/Program.cs

@ -26,23 +26,10 @@ namespace Vote
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureAppConfiguration(builder => AddTyeBindingSecrets(builder))
.ConfigureAppConfiguration(builder => builder.AddTyeSecrets())
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
private static void AddTyeBindingSecrets(IConfigurationBuilder config)
{
if (Directory.Exists("/var/tye/bindings/"))
{
foreach (var directory in Directory.GetDirectories("/var/tye/bindings/"))
{
Console.WriteLine($"Adding config in '{directory}'.");
config.AddKeyPerFile(directory, optional: true);
}
}
}
}
}

4
samples/voting/vote/vote.csproj

@ -4,6 +4,10 @@
<TargetFramework>netcoreapp3.1</TargetFramework>
<RootNamespace>Vote</RootNamespace>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="$(TyeLibrariesPath)\Microsoft.Tye.Extensions.Configuration\Microsoft.Tye.Extensions.Configuration.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Stackexchange.Redis" Version="2.0.601" />

15
samples/voting/worker/Program.cs

@ -19,23 +19,10 @@ namespace Worker
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureAppConfiguration(builder => AddTyeBindingSecrets(builder))
.ConfigureAppConfiguration(builder => builder.AddTyeSecrets())
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
private static void AddTyeBindingSecrets(IConfigurationBuilder config)
{
if (Directory.Exists("/var/tye/bindings/"))
{
foreach (var directory in Directory.GetDirectories("/var/tye/bindings/"))
{
Console.WriteLine($"Adding config in '{directory}'.");
config.AddKeyPerFile(directory, optional: true);
}
}
}
}
}

4
samples/voting/worker/worker.csproj

@ -6,6 +6,10 @@
<RootNamespace>Worker</RootNamespace>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="$(TyeLibrariesPath)\Microsoft.Tye.Extensions.Configuration\Microsoft.Tye.Extensions.Configuration.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="dapper" Version="2.0.30" />
<PackageReference Include="npgsql" Version="4.1.3.1" />

11
src/Microsoft.Tye.Core/KubernetesManifestGenerator.cs

@ -186,7 +186,7 @@ namespace Microsoft.Tye
project.Bindings.Any(b => b.Protocol == "http" || b.Protocol is null) ||
// We generate environment variables for other services if there dependencies
(bindings is object && bindings.Bindings.OfType<EnvironmentVariableInputBinding>().Any()))
(bindings is object && bindings.Bindings.Any()))
{
var env = new YamlSequenceNode();
container.Add("env", env);
@ -210,6 +210,15 @@ namespace Microsoft.Tye
{ "value", new YamlScalarNode(binding.Value) { Style = ScalarStyle.SingleQuoted, } },
});
}
if (bindings.Bindings.OfType<SecretInputBinding>().Any())
{
env.Add(new YamlMappingNode()
{
{ "name", "TYE_SECRETS_PATH" },
{ "value", new YamlScalarNode("/var/tye/bindings/") { Style = ScalarStyle.SingleQuoted, } },
});
}
}
}

11
src/Microsoft.Tye.Extensions.Configuration/Microsoft.Tye.Extensions.Configuration.csproj

@ -0,0 +1,11 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Configuration.KeyPerFile" Version="3.1.3" />
</ItemGroup>
</Project>

53
src/Microsoft.Tye.Extensions.Configuration/TyeSecretsConfigurationBuilderExtensions.cs

@ -0,0 +1,53 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.IO;
using System.Runtime.InteropServices;
using Microsoft.Extensions.FileProviders;
namespace Microsoft.Extensions.Configuration
{
/// <summary>
/// Contains extension methods for adding Tye's secrets to <see cref="IConfiguration" />.
/// </summary>
public static class TyeSecretsConfigurationBuilderExtensions
{
/// <summary>
/// Adds Tye's secrets to <see cref="IConfiguration" />.
/// </summary>
/// <param name="builder">The <see cref="IConfigurationBuilder" />.</param>
/// <param name="configure">A delegate for additional configuration.</param>
/// <returns>The <see cref="IConfigurationBuilder" />.</returns>
/// <remarks>
/// The environment variable <c>TYE_SECRETS_PATH</c> is used to populate the directory used by secrets.
/// When the environment variable is specified, and the specified directory exists, then the value of
/// <see cref="TyeSecretsConfigurationSource.FileProvider" /> will be non-null.
/// </remarks>
public static IConfigurationBuilder AddTyeSecrets(this IConfigurationBuilder builder, Action<TyeSecretsConfigurationSource>? configure = null)
{
TyeSecretsConfigurationSource source;
var secretsDirectory = Environment.GetEnvironmentVariable(TyeSecretsConfigurationSource.TyeSecretsPathEnvironmentVariable);
if (secretsDirectory == null || !Directory.Exists(secretsDirectory))
{
source = new TyeSecretsConfigurationSource()
{
FileProvider = null,
};
}
else
{
source = new TyeSecretsConfigurationSource()
{
FileProvider = new PhysicalFileProvider(secretsDirectory),
};
}
configure?.Invoke(source);
builder.Add(source);
return builder;
}
}
}

37
src/Microsoft.Tye.Extensions.Configuration/TyeSecretsConfigurationSource.cs

@ -0,0 +1,37 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using Microsoft.Extensions.Configuration.KeyPerFile;
using Microsoft.Extensions.FileProviders;
namespace Microsoft.Extensions.Configuration
{
/// <summary>
/// An <see cref="IConfigurationSource" /> implementation for Tye's secrets.
/// </summary>
public sealed class TyeSecretsConfigurationSource : IConfigurationSource
{
/// <summary>
/// The environment variable used to configure the path where Tye looks for secrets.
/// </summary>
public static readonly string TyeSecretsPathEnvironmentVariable = "TYE_SECRETS_PATH";
/// <summary>
/// Gets or sets the <see cref="IFileProvider" /> used by the configuration source.
/// </summary>
public IFileProvider? FileProvider { get; set; }
public IConfigurationProvider Build(IConfigurationBuilder builder)
{
var source = new KeyPerFileConfigurationSource()
{
FileProvider = FileProvider,
Optional = true,
};
return source.Build(builder);
}
}
}

55
test/E2ETest/TestHelpers.cs

@ -68,10 +68,63 @@ namespace E2ETest
return directory;
}
public static DirectoryInfo GetSampleProjectDirectory(string projectName)
{
var directory = new DirectoryInfo(Path.Combine(
TestHelpers.GetSolutionRootDirectory("tye"),
"samples",
projectName));
Assert.True(directory.Exists, $"Project {projectName} not found.");
return directory;
}
internal static TempDirectory CopySampleProjectDirectory(string projectName)
{
var temp = TempDirectory.Create(preferUserDirectoryOnMacOS: true);
DirectoryCopy.Copy(GetSampleProjectDirectory(projectName).FullName, temp.DirectoryPath);
// We need to hijack any P2P references to Tye libraries.
// Test projects must use $(TyeLibrariesPath) to find their references.
var libraryPath = Path.Combine(TestHelpers.GetSolutionRootDirectory("tye"), "src");
if (!libraryPath.EndsWith(Path.DirectorySeparatorChar))
{
libraryPath += Path.DirectorySeparatorChar;
}
File.WriteAllText(
Path.Combine(temp.DirectoryPath, "Directory.Build.props"),
$@"
<Project>
<PropertyGroup>
<TyeLibrariesPath>{libraryPath}</TyeLibrariesPath>
</PropertyGroup>
</Project>");
return temp;
}
internal static TempDirectory CopyTestProjectDirectory(string projectName)
{
var temp = TempDirectory.Create();
var temp = TempDirectory.Create(preferUserDirectoryOnMacOS: true);
DirectoryCopy.Copy(GetTestProjectDirectory(projectName).FullName, temp.DirectoryPath);
// We need to hijack any P2P references to Tye libraries.
// Test projects must use $(TyeLibrariesPath) to find their references.
var libraryPath = Path.Combine(TestHelpers.GetSolutionRootDirectory("tye"), "src");
if (!libraryPath.EndsWith(Path.DirectorySeparatorChar))
{
libraryPath += Path.DirectorySeparatorChar;
}
File.WriteAllText(
Path.Combine(temp.DirectoryPath, "Directory.Build.props"),
$@"
<Project>
<PropertyGroup>
<TyeLibrariesPath>{libraryPath}</TyeLibrariesPath>
</PropertyGroup>
</Project>");
return temp;
}

25
test/E2ETest/TyeBuildTests.cs

@ -6,6 +6,7 @@ using System.IO;
using System.Threading.Tasks;
using Microsoft.Tye;
using Xunit.Abstractions;
using static E2ETest.TestHelpers;
namespace E2ETest
{
@ -29,11 +30,9 @@ namespace E2ETest
var projectName = "single-project";
var environment = "production";
var projectDirectory = new DirectoryInfo(Path.Combine(TestHelpers.GetSolutionRootDirectory("tye"), "samples", projectName));
using var tempDirectory = TempDirectory.Create();
DirectoryCopy.Copy(projectDirectory.FullName, tempDirectory.DirectoryPath);
using var projectDirectory = CopySampleProjectDirectory(projectName);
var projectFile = new FileInfo(Path.Combine(tempDirectory.DirectoryPath, "tye.yaml"));
var projectFile = new FileInfo(Path.Combine(projectDirectory.DirectoryPath, "tye.yaml"));
var outputContext = new OutputContext(sink, Verbosity.Debug);
var application = await ApplicationFactory.CreateAsync(outputContext, projectFile);
@ -62,11 +61,9 @@ namespace E2ETest
var projectName = "frontend-backend";
var environment = "production";
var projectDirectory = new DirectoryInfo(Path.Combine(TestHelpers.GetSolutionRootDirectory("tye"), "samples", projectName));
using var tempDirectory = TempDirectory.Create();
DirectoryCopy.Copy(projectDirectory.FullName, tempDirectory.DirectoryPath);
using var projectDirectory = CopySampleProjectDirectory(projectName);
var projectFile = new FileInfo(Path.Combine(tempDirectory.DirectoryPath, "tye.yaml"));
var projectFile = new FileInfo(Path.Combine(projectDirectory.DirectoryPath, "tye.yaml"));
var outputContext = new OutputContext(sink, Verbosity.Debug);
var application = await ApplicationFactory.CreateAsync(outputContext, projectFile);
@ -98,11 +95,9 @@ namespace E2ETest
var projectName = "multi-project";
var environment = "production";
var projectDirectory = new DirectoryInfo(Path.Combine(TestHelpers.GetSolutionRootDirectory("tye"), "samples", projectName));
using var tempDirectory = TempDirectory.Create();
DirectoryCopy.Copy(projectDirectory.FullName, tempDirectory.DirectoryPath);
using var projectDirectory = CopySampleProjectDirectory(projectName);
var projectFile = new FileInfo(Path.Combine(tempDirectory.DirectoryPath, "tye.yaml"));
var projectFile = new FileInfo(Path.Combine(projectDirectory.DirectoryPath, "tye.yaml"));
var outputContext = new OutputContext(sink, Verbosity.Debug);
var application = await ApplicationFactory.CreateAsync(outputContext, projectFile);
@ -134,11 +129,9 @@ namespace E2ETest
var projectName = "single-project";
var environment = "production";
var projectDirectory = new DirectoryInfo(Path.Combine(TestHelpers.GetSolutionRootDirectory("tye"), "samples", projectName));
using var tempDirectory = TempDirectory.Create();
DirectoryCopy.Copy(projectDirectory.FullName, tempDirectory.DirectoryPath);
using var projectDirectory = CopySampleProjectDirectory(projectName);
var projectFile = new FileInfo(Path.Combine(tempDirectory.DirectoryPath, "tye.yaml"));
var projectFile = new FileInfo(Path.Combine(projectDirectory.DirectoryPath, "tye.yaml"));
var outputContext = new OutputContext(sink, Verbosity.Debug);
var application = await ApplicationFactory.CreateAsync(outputContext, projectFile);

33
test/E2ETest/TyeGenerateTests.cs

@ -8,6 +8,7 @@ using System.Threading.Tasks;
using Microsoft.Tye;
using Xunit;
using Xunit.Abstractions;
using static E2ETest.TestHelpers;
namespace E2ETest
{
@ -31,11 +32,9 @@ namespace E2ETest
var projectName = "single-project";
var environment = "production";
var projectDirectory = new DirectoryInfo(Path.Combine(TestHelpers.GetSolutionRootDirectory("tye"), "samples", projectName));
using var tempDirectory = TempDirectory.Create();
DirectoryCopy.Copy(projectDirectory.FullName, tempDirectory.DirectoryPath);
using var projectDirectory = CopySampleProjectDirectory(projectName);
var projectFile = new FileInfo(Path.Combine(tempDirectory.DirectoryPath, "tye.yaml"));
var projectFile = new FileInfo(Path.Combine(projectDirectory.DirectoryPath, "tye.yaml"));
var outputContext = new OutputContext(sink, Verbosity.Debug);
var application = await ApplicationFactory.CreateAsync(outputContext, projectFile);
@ -48,7 +47,7 @@ namespace E2ETest
await GenerateHost.ExecuteGenerateAsync(outputContext, application, environment, interactive: false);
// name of application is the folder
var content = await File.ReadAllTextAsync(Path.Combine(tempDirectory.DirectoryPath, $"{projectName}-generate-{environment}.yaml"));
var content = await File.ReadAllTextAsync(Path.Combine(projectDirectory.DirectoryPath, $"{projectName}-generate-{environment}.yaml"));
var expectedContent = await File.ReadAllTextAsync($"testassets/generate/{projectName}.yaml");
Assert.Equal(expectedContent.NormalizeNewLines(), content.NormalizeNewLines());
@ -70,11 +69,9 @@ namespace E2ETest
var projectName = "frontend-backend";
var environment = "production";
var projectDirectory = new DirectoryInfo(Path.Combine(TestHelpers.GetSolutionRootDirectory("tye"), "samples", projectName));
using var tempDirectory = TempDirectory.Create();
DirectoryCopy.Copy(projectDirectory.FullName, tempDirectory.DirectoryPath);
using var projectDirectory = CopySampleProjectDirectory(projectName);
var projectFile = new FileInfo(Path.Combine(tempDirectory.DirectoryPath, "tye.yaml"));
var projectFile = new FileInfo(Path.Combine(projectDirectory.DirectoryPath, "tye.yaml"));
var outputContext = new OutputContext(sink, Verbosity.Debug);
var application = await ApplicationFactory.CreateAsync(outputContext, projectFile);
@ -87,7 +84,7 @@ namespace E2ETest
await GenerateHost.ExecuteGenerateAsync(outputContext, application, environment, interactive: false);
// name of application is the folder
var content = await File.ReadAllTextAsync(Path.Combine(tempDirectory.DirectoryPath, $"{projectName}-generate-{environment}.yaml"));
var content = await File.ReadAllTextAsync(Path.Combine(projectDirectory.DirectoryPath, $"{projectName}-generate-{environment}.yaml"));
var expectedContent = await File.ReadAllTextAsync($"testassets/generate/{projectName}.yaml");
Assert.Equal(expectedContent.NormalizeNewLines(), content.NormalizeNewLines());
@ -113,11 +110,9 @@ namespace E2ETest
var projectName = "multi-project";
var environment = "production";
var projectDirectory = new DirectoryInfo(Path.Combine(TestHelpers.GetSolutionRootDirectory("tye"), "samples", projectName));
using var tempDirectory = TempDirectory.Create();
DirectoryCopy.Copy(projectDirectory.FullName, tempDirectory.DirectoryPath);
using var projectDirectory = CopySampleProjectDirectory(projectName);
var projectFile = new FileInfo(Path.Combine(tempDirectory.DirectoryPath, "tye.yaml"));
var projectFile = new FileInfo(Path.Combine(projectDirectory.DirectoryPath, "tye.yaml"));
var outputContext = new OutputContext(sink, Verbosity.Debug);
var application = await ApplicationFactory.CreateAsync(outputContext, projectFile);
@ -130,7 +125,7 @@ namespace E2ETest
await GenerateHost.ExecuteGenerateAsync(outputContext, application, environment, interactive: false);
// name of application is the folder
var content = await File.ReadAllTextAsync(Path.Combine(tempDirectory.DirectoryPath, $"{projectName}-generate-{environment}.yaml"));
var content = await File.ReadAllTextAsync(Path.Combine(projectDirectory.DirectoryPath, $"{projectName}-generate-{environment}.yaml"));
var expectedContent = await File.ReadAllTextAsync($"testassets/generate/{projectName}.yaml");
Assert.Equal(expectedContent.NormalizeNewLines(), content.NormalizeNewLines());
@ -156,11 +151,9 @@ namespace E2ETest
var projectName = "single-project";
var environment = "production";
var projectDirectory = new DirectoryInfo(Path.Combine(TestHelpers.GetSolutionRootDirectory("tye"), "samples", projectName));
using var tempDirectory = TempDirectory.Create();
DirectoryCopy.Copy(projectDirectory.FullName, tempDirectory.DirectoryPath);
using var projectDirectory = CopySampleProjectDirectory("single-project");
var projectFile = new FileInfo(Path.Combine(tempDirectory.DirectoryPath, "tye.yaml"));
var projectFile = new FileInfo(Path.Combine(projectDirectory.DirectoryPath, "tye.yaml"));
var outputContext = new OutputContext(sink, Verbosity.Debug);
var application = await ApplicationFactory.CreateAsync(outputContext, projectFile);
@ -170,7 +163,7 @@ namespace E2ETest
await GenerateHost.ExecuteGenerateAsync(outputContext, application, environment, interactive: false);
// name of application is the folder
var content = await File.ReadAllTextAsync(Path.Combine(tempDirectory.DirectoryPath, $"{projectName}-generate-{environment}.yaml"));
var content = await File.ReadAllTextAsync(Path.Combine(projectDirectory.DirectoryPath, $"{projectName}-generate-{environment}.yaml"));
var expectedContent = await File.ReadAllTextAsync($"testassets/generate/{projectName}-noregistry.yaml");
Assert.Equal(expectedContent.NormalizeNewLines(), content.NormalizeNewLines());

27
test/E2ETest/TyeInitTests.cs

@ -2,11 +2,12 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System;
using System.IO;
using Microsoft.Tye;
using Xunit;
using Xunit.Abstractions;
using static E2ETest.TestHelpers;
namespace E2ETest
{
@ -24,13 +25,11 @@ namespace E2ETest
[Fact]
public void SingleProjectInitTest()
{
var projectDirectory = new DirectoryInfo(Path.Combine(TestHelpers.GetSolutionRootDirectory("tye"), "samples", "single-project", "test-project"));
using var tempDirectory = TempDirectory.Create();
DirectoryCopy.Copy(projectDirectory.FullName, tempDirectory.DirectoryPath);
using var projectDirectory = CopySampleProjectDirectory(Path.Combine("single-project", "test-project"));
File.Delete(Path.Combine(tempDirectory.DirectoryPath, "tye.yaml"));
File.Delete(Path.Combine(projectDirectory.DirectoryPath, "tye.yaml"));
var projectFile = new FileInfo(Path.Combine(tempDirectory.DirectoryPath, "test-project.csproj"));
var projectFile = new FileInfo(Path.Combine(projectDirectory.DirectoryPath, "test-project.csproj"));
var (content, _) = InitHost.CreateTyeFileContent(projectFile, force: false);
var expectedContent = File.ReadAllText("testassets/init/single-project.yaml");
@ -43,14 +42,12 @@ namespace E2ETest
[Fact]
public void MultiProjectInitTest()
{
var projectDirectory = new DirectoryInfo(Path.Combine(TestHelpers.GetSolutionRootDirectory("tye"), "samples", "multi-project"));
using var tempDirectory = TempDirectory.Create();
DirectoryCopy.Copy(projectDirectory.FullName, tempDirectory.DirectoryPath);
using var projectDirectory = CopySampleProjectDirectory("multi-project");
// delete already present yaml
File.Delete(Path.Combine(tempDirectory.DirectoryPath, "tye.yaml"));
File.Delete(Path.Combine(projectDirectory.DirectoryPath, "tye.yaml"));
var projectFile = new FileInfo(Path.Combine(tempDirectory.DirectoryPath, "multi-project.sln"));
var projectFile = new FileInfo(Path.Combine(projectDirectory.DirectoryPath, "multi-project.sln"));
var (content, _) = InitHost.CreateTyeFileContent(projectFile, force: false);
var expectedContent = File.ReadAllText("testassets/init/multi-project.yaml");
@ -63,14 +60,12 @@ namespace E2ETest
[Fact]
public void FrontendBackendTest()
{
var projectDirectory = new DirectoryInfo(Path.Combine(TestHelpers.GetSolutionRootDirectory("tye"), "samples", "frontend-backend"));
using var tempDirectory = TempDirectory.Create();
DirectoryCopy.Copy(projectDirectory.FullName, tempDirectory.DirectoryPath);
using var projectDirectory = CopySampleProjectDirectory("frontend-backend");
// delete already present yaml
File.Delete(Path.Combine(tempDirectory.DirectoryPath, "tye.yaml"));
File.Delete(Path.Combine(projectDirectory.DirectoryPath, "tye.yaml"));
var projectFile = new FileInfo(Path.Combine(tempDirectory.DirectoryPath, "frontend-backend.sln"));
var projectFile = new FileInfo(Path.Combine(projectDirectory.DirectoryPath, "frontend-backend.sln"));
var (content, _) = InitHost.CreateTyeFileContent(projectFile, force: false);
var expectedContent = File.ReadAllText("testassets/init/frontend-backend.yaml");

20
test/E2ETest/TyePurgeTests.cs

@ -4,18 +4,16 @@
using System;
using System.Collections.Generic;
using System.CommandLine;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.Hosting;
using Microsoft.Tye;
using Microsoft.Tye.ConfigModel;
using Microsoft.Tye.Hosting;
using Microsoft.Tye.Hosting.Model;
using Xunit;
using Xunit.Abstractions;
using static E2ETest.TestHelpers;
namespace E2ETest
{
@ -33,12 +31,10 @@ namespace E2ETest
[Fact]
public async Task FrontendBackendPurgeTest()
{
var projectDirectory = new DirectoryInfo(Path.Combine(TestHelpers.GetSolutionRootDirectory("tye"), "samples", "frontend-backend"));
using var tempDirectory = TempDirectory.Create();
DirectoryCopy.Copy(projectDirectory.FullName, tempDirectory.DirectoryPath);
using var projectDirectory = CopySampleProjectDirectory("frontend-backend");
var projectFile = new FileInfo(Path.Combine(tempDirectory.DirectoryPath, "tye.yaml"));
var tyeDir = new DirectoryInfo(Path.Combine(tempDirectory.DirectoryPath, ".tye"));
var projectFile = new FileInfo(Path.Combine(projectDirectory.DirectoryPath, "tye.yaml"));
var tyeDir = new DirectoryInfo(Path.Combine(projectDirectory.DirectoryPath, ".tye"));
var outputContext = new OutputContext(_sink, Verbosity.Debug);
var application = await ApplicationFactory.CreateAsync(outputContext, projectFile);
var host = new TyeHost(application.ToHostingApplication(), Array.Empty<string>())
@ -73,12 +69,10 @@ namespace E2ETest
[SkipIfDockerNotRunning]
public async Task MultiProjectPurgeTest()
{
var projectDirectory = new DirectoryInfo(Path.Combine(TestHelpers.GetSolutionRootDirectory("tye"), "samples", "multi-project"));
using var tempDirectory = TempDirectory.Create();
DirectoryCopy.Copy(projectDirectory.FullName, tempDirectory.DirectoryPath);
using var projectDirectory = CopySampleProjectDirectory("multi-project");
var projectFile = new FileInfo(Path.Combine(tempDirectory.DirectoryPath, "tye.yaml"));
var tyeDir = new DirectoryInfo(Path.Combine(tempDirectory.DirectoryPath, ".tye"));
var projectFile = new FileInfo(Path.Combine(projectDirectory.DirectoryPath, "tye.yaml"));
var tyeDir = new DirectoryInfo(Path.Combine(projectDirectory.DirectoryPath, ".tye"));
var outputContext = new OutputContext(_sink, Verbosity.Debug);
var application = await ApplicationFactory.CreateAsync(outputContext, projectFile);
var host = new TyeHost(application.ToHostingApplication(), Array.Empty<string>())

38
test/E2ETest/TyeRunTests.cs

@ -45,11 +45,9 @@ namespace E2ETest
[Fact]
public async Task SingleProjectRunTest()
{
var projectDirectory = new DirectoryInfo(Path.Combine(TestHelpers.GetSolutionRootDirectory("tye"), "samples", "single-project", "test-project"));
using var tempDirectory = TempDirectory.Create();
DirectoryCopy.Copy(projectDirectory.FullName, tempDirectory.DirectoryPath);
using var projectDirectory = CopySampleProjectDirectory(Path.Combine("single-project", "test-project"));
var projectFile = new FileInfo(Path.Combine(tempDirectory.DirectoryPath, "test-project.csproj"));
var projectFile = new FileInfo(Path.Combine(projectDirectory.DirectoryPath, "test-project.csproj"));
var outputContext = new OutputContext(_sink, Verbosity.Debug);
var application = await ApplicationFactory.CreateAsync(outputContext, projectFile);
@ -74,11 +72,9 @@ namespace E2ETest
[Fact]
public async Task FrontendBackendRunTest()
{
var projectDirectory = new DirectoryInfo(Path.Combine(TestHelpers.GetSolutionRootDirectory("tye"), "samples", "frontend-backend"));
using var tempDirectory = TempDirectory.Create();
DirectoryCopy.Copy(projectDirectory.FullName, tempDirectory.DirectoryPath);
using var projectDirectory = CopySampleProjectDirectory("frontend-backend");
var projectFile = new FileInfo(Path.Combine(tempDirectory.DirectoryPath, "tye.yaml"));
var projectFile = new FileInfo(Path.Combine(projectDirectory.DirectoryPath, "tye.yaml"));
var outputContext = new OutputContext(_sink, Verbosity.Debug);
var application = await ApplicationFactory.CreateAsync(outputContext, projectFile);
@ -107,11 +103,9 @@ namespace E2ETest
[SkipIfDockerNotRunning]
public async Task FrontendBackendRunTestWithDocker()
{
var projectDirectory = new DirectoryInfo(Path.Combine(TestHelpers.GetSolutionRootDirectory("tye"), "samples", "frontend-backend"));
using var tempDirectory = TempDirectory.Create(preferUserDirectoryOnMacOS: true);
DirectoryCopy.Copy(projectDirectory.FullName, tempDirectory.DirectoryPath);
using var projectDirectory = CopySampleProjectDirectory("frontend-backend");
var projectFile = new FileInfo(Path.Combine(tempDirectory.DirectoryPath, "tye.yaml"));
var projectFile = new FileInfo(Path.Combine(projectDirectory.DirectoryPath, "tye.yaml"));
var outputContext = new OutputContext(_sink, Verbosity.Debug);
var application = await ApplicationFactory.CreateAsync(outputContext, projectFile);
@ -143,11 +137,9 @@ namespace E2ETest
[SkipIfDockerNotRunning]
public async Task FrontendProjectBackendDocker()
{
var projectDirectory = new DirectoryInfo(Path.Combine(TestHelpers.GetSolutionRootDirectory("tye"), "samples", "frontend-backend"));
using var tempDirectory = TempDirectory.Create(preferUserDirectoryOnMacOS: true);
DirectoryCopy.Copy(projectDirectory.FullName, tempDirectory.DirectoryPath);
using var projectDirectory = CopySampleProjectDirectory("frontend-backend");
var projectFile = new FileInfo(Path.Combine(tempDirectory.DirectoryPath, "tye.yaml"));
var projectFile = new FileInfo(Path.Combine(projectDirectory.DirectoryPath, "tye.yaml"));
var outputContext = new OutputContext(_sink, Verbosity.Debug);
var application = await ApplicationFactory.CreateAsync(outputContext, projectFile);
@ -253,7 +245,7 @@ namespace E2ETest
// Add a volume
var project = ((ProjectServiceBuilder)application.Services[0]);
using var tempDir = TempDirectory.Create();
using var tempDir = TempDirectory.Create(preferUserDirectoryOnMacOS: true);
project.Volumes.Clear();
project.Volumes.Add(new VolumeBuilder(source: tempDir.DirectoryPath, name: null, target: "/data"));
@ -283,11 +275,9 @@ namespace E2ETest
[Fact]
public async Task IngressRunTest()
{
var projectDirectory = new DirectoryInfo(Path.Combine(TestHelpers.GetSolutionRootDirectory("tye"), "samples", "apps-with-ingress"));
using var tempDirectory = TempDirectory.Create();
DirectoryCopy.Copy(projectDirectory.FullName, tempDirectory.DirectoryPath);
using var projectDirectory = CopySampleProjectDirectory("apps-with-ingress");
var projectFile = new FileInfo(Path.Combine(tempDirectory.DirectoryPath, "tye.yaml"));
var projectFile = new FileInfo(Path.Combine(projectDirectory.DirectoryPath, "tye.yaml"));
var outputContext = new OutputContext(_sink, Verbosity.Debug);
var application = await ApplicationFactory.CreateAsync(outputContext, projectFile);
@ -327,11 +317,9 @@ namespace E2ETest
[Fact]
public async Task NullDebugTargetsDoesNotThrow()
{
var projectDirectory = new DirectoryInfo(Path.Combine(TestHelpers.GetSolutionRootDirectory("tye"), "samples", "single-project", "test-project"));
using var tempDirectory = TempDirectory.Create();
DirectoryCopy.Copy(projectDirectory.FullName, tempDirectory.DirectoryPath);
using var projectDirectory = CopySampleProjectDirectory(Path.Combine("single-project", "test-project"));
var projectFile = new FileInfo(Path.Combine(tempDirectory.DirectoryPath, "test-project.csproj"));
var projectFile = new FileInfo(Path.Combine(projectDirectory.DirectoryPath, "test-project.csproj"));
// Debug targets can be null if not specified, so make sure calling host.Start does not throw.
var outputContext = new OutputContext(_sink, Verbosity.Debug);

6
test/E2ETest/testassets/generate/multi-project.yaml

@ -31,6 +31,8 @@ spec:
value: '8000'
- name: SERVICE__FRONTEND__HOST
value: 'frontend'
- name: TYE_SECRETS_PATH
value: '/var/tye/bindings/'
volumeMounts:
- name: rabbit-rabbit
mountPath: /var/tye/bindings/rabbit-rabbit
@ -97,6 +99,8 @@ spec:
value: '7000'
- name: SERVICE__BACKEND__HOST
value: 'backend'
- name: TYE_SECRETS_PATH
value: '/var/tye/bindings/'
volumeMounts:
- name: rabbit-rabbit
mountPath: /var/tye/bindings/rabbit-rabbit
@ -165,6 +169,8 @@ spec:
value: '8000'
- name: SERVICE__FRONTEND__HOST
value: 'frontend'
- name: TYE_SECRETS_PATH
value: '/var/tye/bindings/'
volumeMounts:
- name: rabbit-rabbit
mountPath: /var/tye/bindings/rabbit-rabbit

8
test/E2ETest/testassets/projects/Directory.Build.props

@ -0,0 +1,8 @@
<Project>
<Import Project="$([MSBuild]::GetDirectoryNameOfFileAbove($(MSBuildThisFileDirectory)..\, Directory.Build.props))\Directory.Build.props" />
<PropertyGroup>
<!-- Used for P2Ps in our samples. The tests know how to set this value so that references work. -->
<TyeLibrariesPath>$(MSBuildThisFileDirectory)..\src\</TyeLibrariesPath>
</PropertyGroup>
</Project>

15
tye.sln

@ -21,6 +21,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tye.Core", "src\Microsoft.T
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Tye.Extensions", "src\Microsoft.Tye.Extensions\Microsoft.Tye.Extensions.csproj", "{AAF0CE0B-E53A-4E10-AA82-BF7200AB2B0C}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Tye.Extensions.Configuration", "src\Microsoft.Tye.Extensions.Configuration\Microsoft.Tye.Extensions.Configuration.csproj", "{B07394E4-30A7-429A-BC5A-747B54D5A447}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@ -115,6 +117,18 @@ Global
{AAF0CE0B-E53A-4E10-AA82-BF7200AB2B0C}.Release|x64.Build.0 = Release|Any CPU
{AAF0CE0B-E53A-4E10-AA82-BF7200AB2B0C}.Release|x86.ActiveCfg = Release|Any CPU
{AAF0CE0B-E53A-4E10-AA82-BF7200AB2B0C}.Release|x86.Build.0 = Release|Any CPU
{B07394E4-30A7-429A-BC5A-747B54D5A447}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{B07394E4-30A7-429A-BC5A-747B54D5A447}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B07394E4-30A7-429A-BC5A-747B54D5A447}.Debug|x64.ActiveCfg = Debug|Any CPU
{B07394E4-30A7-429A-BC5A-747B54D5A447}.Debug|x64.Build.0 = Debug|Any CPU
{B07394E4-30A7-429A-BC5A-747B54D5A447}.Debug|x86.ActiveCfg = Debug|Any CPU
{B07394E4-30A7-429A-BC5A-747B54D5A447}.Debug|x86.Build.0 = Debug|Any CPU
{B07394E4-30A7-429A-BC5A-747B54D5A447}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B07394E4-30A7-429A-BC5A-747B54D5A447}.Release|Any CPU.Build.0 = Release|Any CPU
{B07394E4-30A7-429A-BC5A-747B54D5A447}.Release|x64.ActiveCfg = Release|Any CPU
{B07394E4-30A7-429A-BC5A-747B54D5A447}.Release|x64.Build.0 = Release|Any CPU
{B07394E4-30A7-429A-BC5A-747B54D5A447}.Release|x86.ActiveCfg = Release|Any CPU
{B07394E4-30A7-429A-BC5A-747B54D5A447}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@ -127,6 +141,7 @@ Global
{34719884-1338-4965-BA2A-F98DB03733C2} = {8C662D59-A3CB-466F-8E85-A8E6BA5E7601}
{D0359C69-6EA9-4B03-9455-90E8E04F1CB0} = {8C662D59-A3CB-466F-8E85-A8E6BA5E7601}
{AAF0CE0B-E53A-4E10-AA82-BF7200AB2B0C} = {8C662D59-A3CB-466F-8E85-A8E6BA5E7601}
{B07394E4-30A7-429A-BC5A-747B54D5A447} = {8C662D59-A3CB-466F-8E85-A8E6BA5E7601}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {D8002603-BB27-4500-BF86-274A8E72D302}

Loading…
Cancel
Save