Compare commits

...

4 Commits

  1. 19
      src/Microsoft.Tye.Core/ApplicationFactory.cs
  2. 7
      src/Microsoft.Tye.Core/BindingBuilder.cs
  3. 18
      src/Microsoft.Tye.Core/ConfigModel/ConfigNode.cs
  4. 1
      src/Microsoft.Tye.Core/ConfigModel/ConfigService.cs
  5. 23
      src/Microsoft.Tye.Core/NodeServiceBuilder.cs
  6. 32
      src/Microsoft.Tye.Core/Serialization/ConfigServiceParser.cs
  7. 8
      src/Microsoft.Tye.Extensions/Dapr/DaprExtension.cs
  8. 17
      src/Microsoft.Tye.Hosting/Model/NodeRunInfo.cs
  9. 3
      src/Microsoft.Tye.Hosting/Model/V1/V1RunInfoType.cs
  10. 10
      src/Microsoft.Tye.Hosting/ProcessRunner.cs
  11. 6
      src/Microsoft.Tye.Hosting/TyeDashboardApi.cs
  12. 29
      src/tye/ApplicationBuilderExtensions.cs

19
src/Microsoft.Tye.Core/ApplicationFactory.cs

@ -337,6 +337,25 @@ namespace Microsoft.Tye
var external = new ExternalServiceBuilder(configService.Name, ServiceSource.Configuration);
service = external;
}
else if (configService.Node != null)
{
string packagePath = Path.GetFullPath(Path.Combine(config.Source.Directory!.FullName, configService.Node.Package));
var node = new NodeServiceBuilder(configService.Name, packagePath, ServiceSource.Configuration)
{
EnableDebugging = !configService.Node.EnableDebugging.HasValue || configService.Node.EnableDebugging.Value,
Replicas = configService.Replicas ?? 1,
Script = configService.Node.Script
};
// If debugging but no explicit binding to the Node.js inspector port has been defined, add one...
if (node.EnableDebugging && !node.Bindings.Any(binding => StringComparer.OrdinalIgnoreCase.Equals(binding.Protocol, "inspector")))
{
node.Bindings.Add(new BindingBuilder { Protocol = "inspector" });
}
service = node;
}
else
{
throw new CommandException("Unable to determine service type.");

7
src/Microsoft.Tye.Core/BindingBuilder.cs

@ -2,11 +2,14 @@
// 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;
namespace Microsoft.Tye
{
public sealed class BindingBuilder
public sealed class
BindingBuilder
{
public string? Name { get; set; }
public string? Name { get; set; } = Guid.NewGuid().ToString();
public string? ConnectionString { get; set; }
public int? Port { get; set; }
public int? ContainerPort { get; set; }

18
src/Microsoft.Tye.Core/ConfigModel/ConfigNode.cs

@ -0,0 +1,18 @@
// 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.ComponentModel.DataAnnotations;
namespace Microsoft.Tye.ConfigModel
{
public class ConfigNode
{
public bool? EnableDebugging { get; set; }
[Required]
public string Package { get; set; } = default!;
public string? Script { get; set; } = default!;
}
}

1
src/Microsoft.Tye.Core/ConfigModel/ConfigService.cs

@ -46,5 +46,6 @@ namespace Microsoft.Tye.ConfigModel
public string? Version { get; set; }
public string? Architecture { get; set; }
public string? CloneDirectory { get; internal set; }
public ConfigNode? Node { get; set; }
}
}

23
src/Microsoft.Tye.Core/NodeServiceBuilder.cs

@ -0,0 +1,23 @@
// 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.Collections.Generic;
namespace Microsoft.Tye
{
public class NodeServiceBuilder : LaunchedServiceBuilder
{
public NodeServiceBuilder(string name, string packagePath, ServiceSource source)
: base(name, source)
{
PackagePath = packagePath;
}
public bool EnableDebugging { get; set; } = true;
public string PackagePath { get; set; }
public string? Script { get; set; }
}
}

32
src/Microsoft.Tye.Core/Serialization/ConfigServiceParser.cs

@ -165,6 +165,10 @@ namespace Tye.Serialization
case "cloneDirectory":
service.CloneDirectory = YamlParser.GetScalarValue(key, child.Value);
break;
case "node":
service.Node = new ConfigNode();
HandleNode((YamlMappingNode)child.Value, service.Node);
break;
default:
throw new TyeYamlException(child.Key.Start, CoreStrings.FormatUnrecognizedKey(key));
}
@ -235,6 +239,34 @@ namespace Tye.Serialization
}
}
private static void HandleNode(YamlMappingNode yamlMappingNode, ConfigNode node)
{
foreach (var child in yamlMappingNode.Children)
{
var key = YamlParser.GetScalarValue(child.Key);
switch (key)
{
case "enableDebugging":
if (!bool.TryParse(YamlParser.GetScalarValue(key, child.Value), out var enableDebugging))
{
throw new TyeYamlException(child.Value.Start, CoreStrings.FormatMustBeABoolean(key));
}
node.EnableDebugging = enableDebugging;
break;
case "package":
node.Package = YamlParser.GetScalarValue(key, child.Value);
break;
case "script":
node.Script = YamlParser.GetScalarValue(key, child.Value);
break;
default:
throw new TyeYamlException(child.Key.Start, CoreStrings.FormatUnrecognizedKey(key));
}
}
}
private static void HandleServiceProbe(YamlMappingNode yamlMappingNode, ConfigProbe probe)
{
foreach (var child in yamlMappingNode.Children)

8
src/Microsoft.Tye.Extensions/Dapr/DaprExtension.cs

@ -78,8 +78,14 @@ namespace Microsoft.Tye.Extensions.Dapr
// For local run, enumerate all projects, and add services for each dapr proxy.
var projects = context.Application.Services.OfType<ProjectServiceBuilder>().Cast<LaunchedServiceBuilder>();
// TODO: Is there a better hierarchy to capture all "launched" services (can we just use LaunchedServiceBuilder)?
var node = context.Application.Services.OfType<NodeServiceBuilder>().Cast<LaunchedServiceBuilder>();
var executables = context.Application.Services.OfType<ExecutableServiceBuilder>().Cast<LaunchedServiceBuilder>();
var services = projects.Concat(executables).ToList();
var services =
projects
.Concat(node)
.Concat(executables)
.ToList();
foreach (var project in services)
{

17
src/Microsoft.Tye.Hosting/Model/NodeRunInfo.cs

@ -0,0 +1,17 @@
// 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.
namespace Microsoft.Tye.Hosting.Model
{
public class NodeRunInfo : ExecutableRunInfo
{
public NodeRunInfo(string executable, string? workingDirectory, string? args, bool enableDebugging)
: base(executable, workingDirectory, args)
{
EnableDebugging = enableDebugging;
}
public bool EnableDebugging { get; }
}
}

3
src/Microsoft.Tye.Hosting/Model/V1/V1RunInfoType.cs

@ -8,6 +8,7 @@ namespace Microsoft.Tye.Hosting.Model.V1
{
Project,
Executable,
Docker
Docker,
Node
}
}

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

@ -233,7 +233,8 @@ namespace Microsoft.Tye.Hosting
}
// 3. For non-ASP.NET Core apps, pass the same information in the PORT env variable as a semicolon separated list.
environment["PORT"] = string.Join(";", ports.Select(p => $"{p.Port}"));
var webPorts = ports.Where(port => StringComparer.OrdinalIgnoreCase.Equals(port.Protocol, "http") || StringComparer.OrdinalIgnoreCase.Equals(port.Protocol, "https"));
environment["PORT"] = string.Join(";", webPorts.Select(p => $"{p.Port}"));
if (service.ServiceType == ServiceType.Function)
{
@ -245,6 +246,13 @@ namespace Microsoft.Tye.Hosting
copiedArgs += " --useHttps";
}
}
if (service.Description.RunInfo is NodeRunInfo info && info.EnableDebugging)
{
var binding = ports.First(port => StringComparer.OrdinalIgnoreCase.Equals(port.Protocol, "inspector"));
copiedArgs = $"--inspect={binding.Port} {copiedArgs}";
}
}
var backOff = TimeSpan.FromSeconds(5);

6
src/Microsoft.Tye.Hosting/TyeDashboardApi.cs

@ -167,6 +167,12 @@ namespace Microsoft.Tye.Hosting
v1RunInfo.WorkingDirectory = dockerRunInfo.WorkingDirectory;
v1RunInfo.Args = dockerRunInfo.Args;
break;
case NodeRunInfo nodeRunInfo:
v1RunInfo.Type = V1RunInfoType.Node;
v1RunInfo.Args = nodeRunInfo.Args;
v1RunInfo.Executable = nodeRunInfo.Executable;
v1RunInfo.WorkingDirectory = nodeRunInfo.WorkingDirectory;
break;
case ExecutableRunInfo executableRunInfo:
v1RunInfo.Type = V1RunInfoType.Executable;
v1RunInfo.Args = executableRunInfo.Args;

29
src/tye/ApplicationBuilderExtensions.cs

@ -152,6 +152,35 @@ namespace Microsoft.Tye
liveness = null;
readiness = null;
}
else if (service is NodeServiceBuilder node)
{
string executablePath = "node";
string? workingDirectory = Path.GetDirectoryName(node.PackagePath);
var input = new StringReader(File.ReadAllText(node.PackagePath));
var yaml = new YamlDotNet.RepresentationModel.YamlStream();
yaml.Load(input);
var mapping = (YamlDotNet.RepresentationModel.YamlMappingNode)yaml.Documents[0].RootNode;
var mainNode = (YamlDotNet.RepresentationModel.YamlScalarNode)mapping.Children[new YamlDotNet.RepresentationModel.YamlScalarNode("main")];
var main = mainNode.Value;
string args = $"{main}";
runInfo = new NodeRunInfo(executablePath, workingDirectory, args, node.EnableDebugging);
replicas = node.Replicas;
liveness = null;
readiness = null;
foreach (var entry in node.EnvironmentVariables)
{
env.Add(entry.ToHostingEnvironmentVariable());
}
}
else
{
throw new InvalidOperationException($"Cannot figure out how to run service '{service.Name}'.");

Loading…
Cancel
Save