Browse Source

Make user secrets work in docker scenarios. (#152)

* Make user secrets work in docker scenarios.
- Make build errors show up in the output

* Small nits
davidfowl/dependencies
David Fowler 7 years ago
committed by GitHub
parent
commit
8b81b3d470
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 4
      src/Microsoft.Tye.Core/ProcessUtil.cs
  2. 42
      src/Microsoft.Tye.Hosting/DockerRunner.cs
  3. 8
      src/Microsoft.Tye.Hosting/ProcessRunner.cs
  4. 13
      src/Microsoft.Tye.Hosting/TransformProjectsIntoContainers.cs

4
src/Microsoft.Tye.Core/ProcessUtil.cs

@ -81,10 +81,6 @@ namespace Microsoft.Tye
{
errorDataReceived.Invoke(e.Data);
}
else if (outputDataReceived != null)
{
outputDataReceived.Invoke(e.Data);
}
else
{
errorBuilder.AppendLine(e.Data);

42
src/Microsoft.Tye.Hosting/DockerRunner.cs

@ -4,11 +4,12 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Tye.Hosting.Model;
using Microsoft.Extensions.Logging;
using Microsoft.Tye.Hosting.Model;
namespace Microsoft.Tye.Hosting
{
@ -71,6 +72,15 @@ namespace Microsoft.Tye.Hosting
var volumes = "";
var workingDirectory = docker.WorkingDirectory != null ? $"-w {docker.WorkingDirectory}" : "";
// This is .NET specific
var userSecretStore = GetUserSecretsPathFromSecrets();
if (!string.IsNullOrEmpty(userSecretStore))
{
// Map the user secrets on this drive to user secrets
docker.VolumeMappings[userSecretStore] = "/root/.microsoft/usersecrets:ro";
}
var dockerInfo = new DockerInformation(new Task[service.Description.Replicas]);
async Task RunDockerContainer(IEnumerable<(int Port, int? InternalPort, int BindingPort, string? Protocol)> ports)
@ -260,21 +270,29 @@ namespace Microsoft.Tye.Hosting
}
}
private static async Task<bool> DetectDockerInstalled()
private static string? GetUserSecretsPathFromSecrets()
{
// Detect Docker installation
try
{
await ProcessUtil.RunAsync("docker", "version", throwOnError: false);
return true;
}
catch (Exception)
// This is the logic used to determine the user secrets path
// See https://github.com/dotnet/extensions/blob/64140f90157fec1bfd8aeafdffe8f30308ccdf41/src/Configuration/Config.UserSecrets/src/PathHelper.cs#L27
const string userSecretsFallbackDir = "DOTNET_USER_SECRETS_FALLBACK_DIR";
// For backwards compat, this checks env vars first before using Env.GetFolderPath
var appData = Environment.GetEnvironmentVariable("APPDATA");
var root = appData // On Windows it goes to %APPDATA%\Microsoft\UserSecrets\
?? Environment.GetEnvironmentVariable("HOME") // On Mac/Linux it goes to ~/.microsoft/usersecrets/
?? Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)
?? Environment.GetFolderPath(Environment.SpecialFolder.UserProfile)
?? Environment.GetEnvironmentVariable(userSecretsFallbackDir); // this fallback is an escape hatch if everything else fails
if (string.IsNullOrEmpty(root))
{
// Unfortunately, process throws
return false;
return null;
}
}
return !string.IsNullOrEmpty(appData)
? Path.Combine(root, "Microsoft", "UserSecrets")
: Path.Combine(root, ".microsoft", "usersecrets");
}
private class DockerInformation
{

8
src/Microsoft.Tye.Hosting/ProcessRunner.cs

@ -108,13 +108,13 @@ namespace Microsoft.Tye.Hosting
service.Logs.OnNext($"dotnet build \"{service.Status.ProjectFilePath}\" /nologo");
var buildResult = await ProcessUtil.RunAsync("dotnet", $"build \"{service.Status.ProjectFilePath}\" /nologo",
outputDataReceived: data => service.Logs.OnNext(data),
throwOnError: false);
var buildResult = await ProcessUtil.RunAsync("dotnet", $"build \"{service.Status.ProjectFilePath}\" /nologo", throwOnError: false);
service.Logs.OnNext(buildResult.StandardOutput);
if (buildResult.ExitCode != 0)
{
_logger.LogInformation("Building {ProjectFile} failed with exit code {ExitCode}: " + buildResult.StandardOutput + buildResult.StandardError, service.Status.ProjectFilePath, buildResult.ExitCode);
_logger.LogInformation("Building {ProjectFile} failed with exit code {ExitCode}: \r\n" + buildResult.StandardOutput, service.Status.ProjectFilePath, buildResult.ExitCode);
return;
}
}

13
src/Microsoft.Tye.Hosting/TransformProjectsIntoContainers.cs

@ -50,13 +50,16 @@ namespace Microsoft.Tye.Hosting
service.Logs.OnNext($"dotnet publish \"{service.Status.ProjectFilePath}\" /nologo");
var buildResult = await ProcessUtil.RunAsync("dotnet", $"publish \"{service.Status.ProjectFilePath}\" /nologo",
outputDataReceived: data => service.Logs.OnNext(data),
throwOnError: false);
var buildResult = await ProcessUtil.RunAsync("dotnet", $"publish \"{service.Status.ProjectFilePath}\" /nologo", throwOnError: false);
service.Logs.OnNext(buildResult.StandardOutput);
if (buildResult.ExitCode != 0)
{
_logger.LogInformation("Publishing {ProjectFile} failed with exit code {ExitCode}: " + buildResult.StandardOutput + buildResult.StandardError, service.Status.ProjectFilePath, buildResult.ExitCode);
_logger.LogInformation("Publishing {ProjectFile} failed with exit code {ExitCode}: \r\n" + buildResult.StandardOutput, service.Status.ProjectFilePath, buildResult.ExitCode);
// Null out the RunInfo so that
serviceDescription.RunInfo = null;
return;
}
@ -78,7 +81,7 @@ namespace Microsoft.Tye.Hosting
private static string DetermineContainerImage(string targetFramework)
{
// TODO: Determine the base iamge from the tfm
// TODO: Determine the base image from the tfm
return "mcr.microsoft.com/dotnet/core/sdk:3.1-buster";
}

Loading…
Cancel
Save