diff --git a/docs/redis.md b/docs/redis.md index 3c506a7c..369a7ff3 100644 --- a/docs/redis.md +++ b/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 => { diff --git a/samples/Directory.Build.props b/samples/Directory.Build.props index 2bb6feeb..7ffc010b 100644 --- a/samples/Directory.Build.props +++ b/samples/Directory.Build.props @@ -7,5 +7,8 @@ $(OutDirName)$(Configuration)\ $([System.IO.Path]::GetFullPath('$(MSBuildProjectDirectory)\obj\')) $(BaseIntermediateOutputPath)$(Configuration) + + + $(MSBuildThisFileDirectory)\..\src\ \ No newline at end of file diff --git a/samples/multi-project/backend/Program.cs b/samples/multi-project/backend/Program.cs index f7790a1a..b17012e6 100644 --- a/samples/multi-project/backend/Program.cs +++ b/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 => { diff --git a/samples/multi-project/backend/backend.csproj b/samples/multi-project/backend/backend.csproj index 07b43835..4bf76166 100644 --- a/samples/multi-project/backend/backend.csproj +++ b/samples/multi-project/backend/backend.csproj @@ -6,7 +6,10 @@ - + + + + diff --git a/samples/multi-project/frontend/Program.cs b/samples/multi-project/frontend/Program.cs index d5277964..aa339d68 100644 --- a/samples/multi-project/frontend/Program.cs +++ b/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 => { diff --git a/samples/multi-project/frontend/frontend.csproj b/samples/multi-project/frontend/frontend.csproj index 4a763c86..106957d7 100644 --- a/samples/multi-project/frontend/frontend.csproj +++ b/samples/multi-project/frontend/frontend.csproj @@ -5,7 +5,10 @@ - + + + + diff --git a/samples/multi-project/worker/Program.cs b/samples/multi-project/worker/Program.cs index 776b471b..9a5c1fe3 100644 --- a/samples/multi-project/worker/Program.cs +++ b/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) => { diff --git a/samples/multi-project/worker/worker.csproj b/samples/multi-project/worker/worker.csproj index 75cb35fb..b30b0e7a 100644 --- a/samples/multi-project/worker/worker.csproj +++ b/samples/multi-project/worker/worker.csproj @@ -7,8 +7,11 @@ - - + + + + + diff --git a/samples/voting/vote/Program.cs b/samples/voting/vote/Program.cs index ae831202..f6fc67cb 100644 --- a/samples/voting/vote/Program.cs +++ b/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(); }); - - - 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); - } - } - } } } diff --git a/samples/voting/vote/vote.csproj b/samples/voting/vote/vote.csproj index 232802f8..ed4c23aa 100644 --- a/samples/voting/vote/vote.csproj +++ b/samples/voting/vote/vote.csproj @@ -4,6 +4,10 @@ netcoreapp3.1 Vote + + + + diff --git a/samples/voting/worker/Program.cs b/samples/voting/worker/Program.cs index 3b06bb9e..d9997c90 100644 --- a/samples/voting/worker/Program.cs +++ b/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(); }); - - - 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); - } - } - } } } diff --git a/samples/voting/worker/worker.csproj b/samples/voting/worker/worker.csproj index df2528cb..fe7d9b49 100644 --- a/samples/voting/worker/worker.csproj +++ b/samples/voting/worker/worker.csproj @@ -6,6 +6,10 @@ Worker + + + + diff --git a/src/Microsoft.Tye.Core/KubernetesManifestGenerator.cs b/src/Microsoft.Tye.Core/KubernetesManifestGenerator.cs index ec295dfa..6de5595f 100644 --- a/src/Microsoft.Tye.Core/KubernetesManifestGenerator.cs +++ b/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().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().Any()) + { + env.Add(new YamlMappingNode() + { + { "name", "TYE_SECRETS_PATH" }, + { "value", new YamlScalarNode("/var/tye/bindings/") { Style = ScalarStyle.SingleQuoted, } }, + }); + } } } diff --git a/src/Microsoft.Tye.Extensions.Configuration/Microsoft.Tye.Extensions.Configuration.csproj b/src/Microsoft.Tye.Extensions.Configuration/Microsoft.Tye.Extensions.Configuration.csproj new file mode 100644 index 00000000..9cdf60fb --- /dev/null +++ b/src/Microsoft.Tye.Extensions.Configuration/Microsoft.Tye.Extensions.Configuration.csproj @@ -0,0 +1,11 @@ + + + + netstandard2.0 + + + + + + + diff --git a/src/Microsoft.Tye.Extensions.Configuration/TyeSecretsConfigurationBuilderExtensions.cs b/src/Microsoft.Tye.Extensions.Configuration/TyeSecretsConfigurationBuilderExtensions.cs new file mode 100644 index 00000000..e340c98f --- /dev/null +++ b/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 +{ + /// + /// Contains extension methods for adding Tye's secrets to . + /// + public static class TyeSecretsConfigurationBuilderExtensions + { + /// + /// Adds Tye's secrets to . + /// + /// The . + /// A delegate for additional configuration. + /// The . + /// + /// The environment variable TYE_SECRETS_PATH is used to populate the directory used by secrets. + /// When the environment variable is specified, and the specified directory exists, then the value of + /// will be non-null. + /// + public static IConfigurationBuilder AddTyeSecrets(this IConfigurationBuilder builder, Action? 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; + } + } +} diff --git a/src/Microsoft.Tye.Extensions.Configuration/TyeSecretsConfigurationSource.cs b/src/Microsoft.Tye.Extensions.Configuration/TyeSecretsConfigurationSource.cs new file mode 100644 index 00000000..6f7233dc --- /dev/null +++ b/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 +{ + /// + /// An implementation for Tye's secrets. + /// + public sealed class TyeSecretsConfigurationSource : IConfigurationSource + { + /// + /// The environment variable used to configure the path where Tye looks for secrets. + /// + public static readonly string TyeSecretsPathEnvironmentVariable = "TYE_SECRETS_PATH"; + + /// + /// Gets or sets the used by the configuration source. + /// + public IFileProvider? FileProvider { get; set; } + + public IConfigurationProvider Build(IConfigurationBuilder builder) + { + var source = new KeyPerFileConfigurationSource() + { + FileProvider = FileProvider, + Optional = true, + }; + + return source.Build(builder); + + } + } +} diff --git a/test/E2ETest/TestHelpers.cs b/test/E2ETest/TestHelpers.cs index bc025b34..156a44e6 100644 --- a/test/E2ETest/TestHelpers.cs +++ b/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"), + $@" + + + {libraryPath} + +"); + + 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"), + $@" + + + {libraryPath} + +"); + return temp; } diff --git a/test/E2ETest/TyeBuildTests.cs b/test/E2ETest/TyeBuildTests.cs index 43065786..7b8fcaeb 100644 --- a/test/E2ETest/TyeBuildTests.cs +++ b/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); diff --git a/test/E2ETest/TyeGenerateTests.cs b/test/E2ETest/TyeGenerateTests.cs index 5eaa541a..dfb126b5 100644 --- a/test/E2ETest/TyeGenerateTests.cs +++ b/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()); diff --git a/test/E2ETest/TyeInitTests.cs b/test/E2ETest/TyeInitTests.cs index 203f07a9..c85d94aa 100644 --- a/test/E2ETest/TyeInitTests.cs +++ b/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"); diff --git a/test/E2ETest/TyePurgeTests.cs b/test/E2ETest/TyePurgeTests.cs index a5c2e1da..85574dbd 100644 --- a/test/E2ETest/TyePurgeTests.cs +++ b/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()) @@ -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()) diff --git a/test/E2ETest/TyeRunTests.cs b/test/E2ETest/TyeRunTests.cs index b09450bd..08c34c1f 100644 --- a/test/E2ETest/TyeRunTests.cs +++ b/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); diff --git a/test/E2ETest/testassets/generate/multi-project.yaml b/test/E2ETest/testassets/generate/multi-project.yaml index 9f2a3074..eb62f0e4 100644 --- a/test/E2ETest/testassets/generate/multi-project.yaml +++ b/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 diff --git a/test/E2ETest/testassets/projects/Directory.Build.props b/test/E2ETest/testassets/projects/Directory.Build.props new file mode 100644 index 00000000..fa576708 --- /dev/null +++ b/test/E2ETest/testassets/projects/Directory.Build.props @@ -0,0 +1,8 @@ + + + + + + $(MSBuildThisFileDirectory)..\src\ + + \ No newline at end of file diff --git a/tye.sln b/tye.sln index 7b617abb..766b7725 100644 --- a/tye.sln +++ b/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}