Browse Source

add environment variable token replacement

pull/1611/head
Phill Morton 3 years ago
parent
commit
b256a12bfc
  1. 3
      src/Microsoft.Tye.Hosting/Model/Application.cs
  2. 64
      src/Microsoft.Tye.Hosting/TokenReplacement.cs

3
src/Microsoft.Tye.Hosting/Model/Application.cs

@ -50,9 +50,10 @@ namespace Microsoft.Tye.Hosting.Model
// Inject normal configuration
foreach (var pair in service.Description.Configuration)
{
if (pair.Value is object)
{
set(pair.Name, pair.Value);
set(pair.Name, TokenReplacement.ReplaceEnvironmentValues(pair.Value, bindings));
}
else if (pair.Source is object)
{

64
src/Microsoft.Tye.Hosting/TokenReplacement.cs

@ -12,6 +12,29 @@ namespace Microsoft.Tye.Hosting
{
internal static class TokenReplacement
{
public static string ReplaceEnvironmentValues(string text, List<EffectiveBinding> bindings)
{
var tokens = GetTokens(text);
foreach (var token in tokens)
{
var selectedBinding = ResolveEnvironmentToken(token, bindings);
if (selectedBinding is null)
{
throw new InvalidOperationException($"No available substitutions found for token '{token}'.");
}
text = selectedBinding.Value.Item2;
var selectedBindingtokens = GetTokens(selectedBinding.Value.Item2);
foreach (var bindingtoken in selectedBindingtokens)
{
var replacement = ReplaceValues(bindingtoken,selectedBinding.Value.Item1, bindings);
text = text.Replace(bindingtoken, replacement);
}
}
return text;
}
public static string ReplaceValues(string text, EffectiveBinding binding, List<EffectiveBinding> bindings)
{
var tokens = GetTokens(text);
@ -58,6 +81,47 @@ namespace Microsoft.Tye.Hosting
return tokens;
}
private static (EffectiveBinding, string?)? ResolveEnvironmentToken(string token, List<EffectiveBinding> bindings)
{
// The language we support for tokens is meant to be pretty DRY. It supports a few different formats:
//
// - ${host}: only allowed inside a connection string, it can refer to the binding.
// - ${env:SOME_VAR}: allowed anywhere. It can refer to any environment variable defined for *this* service.
// - ${service:myservice:port}: allowed anywhere. It can refer to the protocol/host/port of bindings.
var keys = token[2..^1].Split(':');
if (keys.Length == 3 && keys[0] == "service")
{
var binding = bindings.FirstOrDefault(b => b.Service == keys[1] && b.Name == null)!;
return (binding, GetValueFromBinding(binding, keys[2]));
}
else if (keys.Length == 4 && keys[0] == "service")
{
var binding = bindings.FirstOrDefault(b => b.Service == keys[1] && b.Name == keys[2])!;
return (binding, GetValueFromBinding(binding, keys[3]));
}
return null;
string? GetValueFromBinding(EffectiveBinding binding, string key)
{
return key switch
{
"protocol" => binding.Protocol,
"host" => binding.Host,
"port" => binding.Port?.ToString(CultureInfo.InvariantCulture),
"connectionString" => binding.ConnectionString,
_ => null,
};
}
static string? GetEnvironmentVariable(EffectiveBinding binding, string key)
{
var envVar = binding.Env.FirstOrDefault(e => string.Equals(e.Name, key, StringComparison.OrdinalIgnoreCase));
return envVar?.Value;
}
}
private static string? ResolveToken(string token, EffectiveBinding binding, List<EffectiveBinding> bindings)
{

Loading…
Cancel
Save