Browse Source

Create new json objects for service models (#154)

pull/162/head
Justin Kotalik 6 years ago
committed by GitHub
parent
commit
0d05542e3f
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 19
      src/Microsoft.Tye.Hosting/Model/ConfigurationSource.cs
  2. 19
      src/Microsoft.Tye.Hosting/Model/DockerStatus.cs
  3. 15
      src/Microsoft.Tye.Hosting/Model/PortMapping.cs
  4. 20
      src/Microsoft.Tye.Hosting/Model/ProcessStatus.cs
  5. 18
      src/Microsoft.Tye.Hosting/Model/ReplicaEvent.cs
  6. 14
      src/Microsoft.Tye.Hosting/Model/ReplicaState.cs
  7. 27
      src/Microsoft.Tye.Hosting/Model/ReplicaStatus.cs
  8. 111
      src/Microsoft.Tye.Hosting/Model/Service.cs
  9. 14
      src/Microsoft.Tye.Hosting/Model/ServiceDescription.cs
  10. 14
      src/Microsoft.Tye.Hosting/Model/ServiceStatus.cs
  11. 14
      src/Microsoft.Tye.Hosting/Model/ServiceType.cs
  12. 12
      src/Microsoft.Tye.Hosting/Model/V1/V1ConfigurationSource.cs
  13. 24
      src/Microsoft.Tye.Hosting/Model/V1/V1ReplicaStatus.cs
  14. 12
      src/Microsoft.Tye.Hosting/Model/V1/V1ReplicaType.cs
  15. 20
      src/Microsoft.Tye.Hosting/Model/V1/V1RunInfo.cs
  16. 13
      src/Microsoft.Tye.Hosting/Model/V1/V1RunInfoType.cs
  17. 17
      src/Microsoft.Tye.Hosting/Model/V1/V1Service.cs
  18. 17
      src/Microsoft.Tye.Hosting/Model/V1/V1ServiceBinding.cs
  19. 17
      src/Microsoft.Tye.Hosting/Model/V1/V1ServiceDescription.cs
  20. 14
      src/Microsoft.Tye.Hosting/Model/V1/V1ServiceStatus.cs
  21. 111
      src/Microsoft.Tye.Hosting/TyeDashboardApi.cs
  22. 49
      test/E2ETest/TyeRunTests.cs

19
src/Microsoft.Tye.Hosting/Model/ConfigurationSource.cs

@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Microsoft.Tye.Hosting.Model
{
public class ConfigurationSource
{
public ConfigurationSource(string name, string value)
{
Name = name;
Value = value;
}
public string Name { get; }
public string Value { get; }
}
}

19
src/Microsoft.Tye.Hosting/Model/DockerStatus.cs

@ -0,0 +1,19 @@
// 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 DockerStatus : ReplicaStatus
{
public DockerStatus(Service service, string name) : base(service, name)
{
}
public string? DockerCommand { get; set; }
public string? ContainerId { get; set; }
public int? DockerLogsPid { get; set; }
}
}

15
src/Microsoft.Tye.Hosting/Model/PortMapping.cs

@ -0,0 +1,15 @@
// 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.Hosting.Model
{
public class PortMapping
{
public int ExternalPort { get; set; }
public List<int> InternalPorts { get; set; } = new List<int>();
}
}

20
src/Microsoft.Tye.Hosting/Model/ProcessStatus.cs

@ -0,0 +1,20 @@
// 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.Hosting.Model
{
public class ProcessStatus : ReplicaStatus
{
public ProcessStatus(Service service, string name)
: base(service, name)
{
}
public int? ExitCode { get; set; }
public int? Pid { get; set; }
public IDictionary<string, string>? Environment { get; set; }
}
}

18
src/Microsoft.Tye.Hosting/Model/ReplicaEvent.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.
namespace Microsoft.Tye.Hosting.Model
{
public readonly struct ReplicaEvent
{
public ReplicaState State { get; }
public ReplicaStatus Replica { get; }
public ReplicaEvent(ReplicaState state, ReplicaStatus replica)
{
State = state;
Replica = replica;
}
}
}

14
src/Microsoft.Tye.Hosting/Model/ReplicaState.cs

@ -0,0 +1,14 @@
// 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 enum ReplicaState
{
Removed,
Added,
Started,
Stopped,
}
}

27
src/Microsoft.Tye.Hosting/Model/ReplicaStatus.cs

@ -0,0 +1,27 @@
// 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.Hosting.Model
{
public class ReplicaStatus
{
public ReplicaStatus(Service service, string name)
{
Service = service;
Name = name;
}
public string Name { get; }
public IEnumerable<int>? Ports { get; set; }
public Service Service { get; }
public Dictionary<object, object> Items { get; } = new Dictionary<object, object>();
public Dictionary<string, string> Metrics { get; set; } = new Dictionary<string, string>();
}
}

111
src/Microsoft.Tye.Hosting/Model/Service.cs

@ -6,7 +6,6 @@ using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Reactive.Subjects;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace Microsoft.Tye.Hosting.Model
@ -59,124 +58,14 @@ namespace Microsoft.Tye.Hosting.Model
public ConcurrentDictionary<string, ReplicaStatus> Replicas { get; set; } = new ConcurrentDictionary<string, ReplicaStatus>();
[JsonIgnore]
public Dictionary<int, List<int>> PortMap { get; set; } = new Dictionary<int, List<int>>();
[JsonIgnore]
public Dictionary<object, object> Items { get; } = new Dictionary<object, object>();
[JsonIgnore]
public Queue<string> CachedLogs { get; } = new Queue<string>();
[JsonIgnore]
public Subject<string> Logs { get; } = new Subject<string>();
[JsonIgnore]
public Subject<ReplicaEvent> ReplicaEvents { get; } = new Subject<ReplicaEvent>();
}
public readonly struct ReplicaEvent
{
public ReplicaState State { get; }
public ReplicaStatus Replica { get; }
public ReplicaEvent(ReplicaState state, ReplicaStatus replica)
{
State = state;
Replica = replica;
}
}
public enum ReplicaState
{
Removed,
Added,
Started,
Stopped,
}
public class ServiceStatus
{
public string? ProjectFilePath { get; set; }
public string? ExecutablePath { get; set; }
public string? Args { get; set; }
public string? WorkingDirectory { get; set; }
}
public class ProcessStatus : ReplicaStatus
{
public ProcessStatus(Service service, string name)
: base(service, name)
{
}
public int? ExitCode { get; set; }
public int? Pid { get; set; }
public IDictionary<string, string>? Environment { get; set; }
}
public class DockerStatus : ReplicaStatus
{
public DockerStatus(Service service, string name) : base(service, name)
{
}
public string? DockerCommand { get; set; }
public string? ContainerId { get; set; }
public int? DockerLogsPid { get; set; }
}
public class ReplicaStatus
{
public ReplicaStatus(Service service, string name)
{
Service = service;
Name = name;
}
public string Name { get; }
public static JsonConverter<ReplicaStatus> JsonConverter = new Converter();
public IEnumerable<int>? Ports { get; set; }
[JsonIgnore]
public Service Service { get; }
[JsonIgnore]
public Dictionary<object, object> Items { get; } = new Dictionary<object, object>();
[JsonIgnore]
public Dictionary<string, string> Metrics { get; set; } = new Dictionary<string, string>();
private class Converter : JsonConverter<ReplicaStatus>
{
public override ReplicaStatus Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
throw new NotImplementedException();
}
public override void Write(Utf8JsonWriter writer, ReplicaStatus value, JsonSerializerOptions options)
{
// Use the runtime type since we really want to serialize either the DockerStatus or ProcessStatus
JsonSerializer.Serialize(writer, value, value.GetType(), options);
}
}
}
public enum ServiceType
{
External,
Project,
Executable,
Container
}
public class PortMapping
{
public int ExternalPort { get; set; }
public List<int> InteralPorts { get; set; } = new List<int>();
}
}

14
src/Microsoft.Tye.Hosting/Model/ServiceDescription.cs

@ -15,23 +15,9 @@ namespace Microsoft.Tye.Hosting.Model
}
public string Name { get; }
public RunInfo? RunInfo { get; set; }
public int Replicas { get; set; } = 1;
public List<ServiceBinding> Bindings { get; } = new List<ServiceBinding>();
public List<ConfigurationSource> Configuration { get; } = new List<ConfigurationSource>();
}
public class ConfigurationSource
{
public ConfigurationSource(string name, string value)
{
Name = name;
Value = value;
}
public string Name { get; }
public string Value { get; }
}
}

14
src/Microsoft.Tye.Hosting/Model/ServiceStatus.cs

@ -0,0 +1,14 @@
// 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 ServiceStatus
{
public string? ProjectFilePath { get; set; }
public string? ExecutablePath { get; set; }
public string? Args { get; set; }
public string? WorkingDirectory { get; set; }
}
}

14
src/Microsoft.Tye.Hosting/Model/ServiceType.cs

@ -0,0 +1,14 @@
// 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 enum ServiceType
{
External,
Project,
Executable,
Container
}
}

12
src/Microsoft.Tye.Hosting/Model/V1/V1ConfigurationSource.cs

@ -0,0 +1,12 @@
// 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.V1
{
public class V1ConfigurationSource
{
public string? Name { get; set; }
public string? Value { get; set; }
}
}

24
src/Microsoft.Tye.Hosting/Model/V1/V1ReplicaStatus.cs

@ -0,0 +1,24 @@
// 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.Collections.Generic;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace Microsoft.Tye.Hosting.Model.V1
{
public class V1ReplicaStatus
{
public V1ReplicaType Type { get; set; }
public string? DockerCommand { get; set; }
public string? ContainerId { get; set; }
public int? DockerLogsPid { get; set; }
public string? Name { get; set; }
public IEnumerable<int>? Ports { get; set; }
public int? ExitCode { get; set; }
public int? Pid { get; set; }
public IDictionary<string, string>? Environment { get; set; }
}
}

12
src/Microsoft.Tye.Hosting/Model/V1/V1ReplicaType.cs

@ -0,0 +1,12 @@
// 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.V1
{
public enum V1ReplicaType
{
Process,
Docker
}
}

20
src/Microsoft.Tye.Hosting/Model/V1/V1RunInfo.cs

@ -0,0 +1,20 @@
// 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.Hosting.Model.V1
{
public class V1RunInfo
{
public V1RunInfoType Type { get; set; }
public string? Args { get; set; }
public bool Build { get; set; }
public string? Project { get; set; }
public string? WorkingDirectory { get; set; }
public Dictionary<string, string>? VolumeMappings { get; set; }
public string? Image { get; set; }
public string? Executable { get; set; }
}
}

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

@ -0,0 +1,13 @@
// 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.V1
{
public enum V1RunInfoType
{
Project,
Executable,
Docker
}
}

17
src/Microsoft.Tye.Hosting/Model/V1/V1Service.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.
using System.Collections.Generic;
namespace Microsoft.Tye.Hosting.Model.V1
{
public class V1Service
{
public V1ServiceDescription? Description { get; set; }
public ServiceType ServiceType { get; set; }
public int Restarts { get; set; }
public V1ServiceStatus? Status { get; set; }
public Dictionary<string, V1ReplicaStatus>? Replicas { get; set; }
}
}

17
src/Microsoft.Tye.Hosting/Model/V1/V1ServiceBinding.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.V1
{
public class V1ServiceBinding
{
public string? Name { get; set; }
public string? ConnectionString { get; set; }
public bool AutoAssignPort { get; set; }
public int? Port { get; set; }
public int? InternalPort { get; set; }
public string? Host { get; set; }
public string? Protocol { get; set; }
}
}

17
src/Microsoft.Tye.Hosting/Model/V1/V1ServiceDescription.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.
using System.Collections.Generic;
namespace Microsoft.Tye.Hosting.Model.V1
{
public class V1ServiceDescription
{
public string? Name { get; set; }
public int Replicas { get; set; }
public V1RunInfo? RunInfo { get; set; }
public List<V1ServiceBinding>? Bindings { get; set; }
public List<V1ConfigurationSource>? Configuration { get; set; }
}
}

14
src/Microsoft.Tye.Hosting/Model/V1/V1ServiceStatus.cs

@ -0,0 +1,14 @@
// 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.V1
{
public class V1ServiceStatus
{
public string? ProjectFilePath { get; set; }
public string? ExecutablePath { get; set; }
public string? Args { get; set; }
public string? WorkingDirectory { get; set; }
}
}

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

@ -11,6 +11,9 @@ using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Routing;
using Microsoft.Extensions.DependencyInjection;
using System.Text.Json.Serialization;
using System.Collections.Generic;
using Microsoft.Tye.Hosting.Model.V1;
namespace Microsoft.Tye.Hosting
{
@ -27,7 +30,7 @@ namespace Microsoft.Tye.Hosting
WriteIndented = true,
};
_options.Converters.Add(ReplicaStatus.JsonConverter);
_options.Converters.Add(new JsonStringEnumConverter(JsonNamingPolicy.CamelCase));
}
public void MapRoutes(IEndpointRouteBuilder endpoints)
@ -61,7 +64,13 @@ namespace Microsoft.Tye.Hosting
var services = app.Services.OrderBy(s => s.Key).Select(s => s.Value);
await JsonSerializer.SerializeAsync(context.Response.Body, services, _options);
var list = new List<V1Service>();
foreach (var service in services)
{
list.Add(CreateServiceJson(service));
}
await JsonSerializer.SerializeAsync(context.Response.Body, list, _options);
}
private async Task Service(HttpContext context)
@ -83,7 +92,103 @@ namespace Microsoft.Tye.Hosting
return;
}
await JsonSerializer.SerializeAsync(context.Response.Body, service, _options);
var serviceJson = CreateServiceJson(service);
await JsonSerializer.SerializeAsync(context.Response.Body, serviceJson, _options);
}
private static V1Service CreateServiceJson(Model.Service service)
{
var description = service.Description;
var bindings = description.Bindings;
var v1bindingList = new List<V1ServiceBinding>();
foreach (var binding in bindings)
{
v1bindingList.Add(new V1ServiceBinding()
{
Name = binding.Name,
ConnectionString = binding.ConnectionString,
AutoAssignPort = binding.AutoAssignPort,
Port = binding.Port,
InternalPort = binding.InternalPort,
Host = binding.Host,
Protocol = binding.Protocol
});
}
var v1ConfigurationSourceList = new List<V1ConfigurationSource>();
foreach (var configSource in description.Configuration)
{
v1ConfigurationSourceList.Add(new V1ConfigurationSource()
{
Name = configSource.Name,
Value = configSource.Value
});
}
var v1RunInfo = new V1RunInfo();
if (description.RunInfo is DockerRunInfo dockerRunInfo)
{
v1RunInfo.Type = V1RunInfoType.Docker;
v1RunInfo.Image = dockerRunInfo.Image;
v1RunInfo.VolumeMappings = dockerRunInfo.VolumeMappings;
v1RunInfo.WorkingDirectory = dockerRunInfo.WorkingDirectory;
v1RunInfo.Args = dockerRunInfo.Args;
}
else if (description.RunInfo is ExecutableRunInfo executableRunInfo)
{
v1RunInfo.Type = V1RunInfoType.Executable;
v1RunInfo.Args = executableRunInfo.Args;
v1RunInfo.Executable = executableRunInfo.Executable;
v1RunInfo.WorkingDirectory = executableRunInfo.WorkingDirectory;
}
else if (description.RunInfo is ProjectRunInfo projectRunInfo)
{
v1RunInfo.Type = V1RunInfoType.Project;
v1RunInfo.Args = projectRunInfo.Args;
v1RunInfo.Build = projectRunInfo.Build;
v1RunInfo.Project = projectRunInfo.Project;
}
var v1ServiceDescription = new V1ServiceDescription()
{
Bindings = v1bindingList,
Configuration = v1ConfigurationSourceList,
Name = description.Name,
Replicas = description.Replicas,
RunInfo = v1RunInfo
};
var replicateDictionary = new Dictionary<string, V1ReplicaStatus>();
foreach (var replica in service.Replicas)
{
replicateDictionary[replica.Key] = new V1ReplicaStatus()
{
Name = replica.Value.Name,
Ports = replica.Value.Ports
};
}
var v1Status = new V1ServiceStatus()
{
ProjectFilePath = service.Status.ProjectFilePath,
ExecutablePath = service.Status.ExecutablePath,
Args = service.Status.Args,
WorkingDirectory = service.Status.WorkingDirectory,
};
var serviceJson = new V1Service()
{
ServiceType = service.ServiceType,
Status = v1Status,
Description = v1ServiceDescription,
Replicas = replicateDictionary,
Restarts = service.Restarts
};
return serviceJson;
}
private async Task Logs(HttpContext context)

49
test/E2ETest/TyeRunTests.cs

@ -8,11 +8,14 @@ using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Threading.Tasks;
using Microsoft.Tye;
using Microsoft.Tye.ConfigModel;
using Microsoft.Tye.Hosting;
using Microsoft.Tye.Hosting.Model;
using Microsoft.Tye.Hosting.Model.V1;
using Xunit;
using Xunit.Abstractions;
@ -22,11 +25,21 @@ namespace E2ETest
{
private readonly ITestOutputHelper output;
private readonly TestOutputLogEventSink sink;
private readonly JsonSerializerOptions _options;
public TyeRunTests(ITestOutputHelper output)
{
this.output = output;
sink = new TestOutputLogEventSink(output);
_options = new JsonSerializerOptions()
{
PropertyNameCaseInsensitive = true,
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
WriteIndented = true,
};
_options.Converters.Add(new JsonStringEnumConverter(JsonNamingPolicy.CamelCase));
}
[Fact]
@ -56,21 +69,11 @@ namespace E2ETest
// Make sure dashboard and applications are up.
// Dashboard should be hosted in same process.
var dashboardUri = new Uri(host.DashboardWebApplication!.Addresses.First());
var dashboardResponse = await client.GetStringAsync(dashboardUri);
// Only one service for single application.
var service = host.Application.Services.First().Value;
var binding = service.Description.Bindings.First();
var protocol = binding.Protocol?.Length != 0 ? binding.Protocol : "http";
var hostName = binding.Host != null && binding.Host.Length != 0 ? binding.Host : "localhost";
var dashboardString = await client.GetStringAsync($"{dashboardUri}api/v1/services/test-project");
var uriString = $"{protocol}://{hostName}:{binding.Port}";
// Confirm that the uri is in the dashboard response.
Assert.Contains(uriString, dashboardResponse);
var uriBackendProcess = new Uri(uriString);
var service = JsonSerializer.Deserialize<V1Service>(dashboardString, _options);
var binding = service.Description!.Bindings.Where(b => b.Protocol == "http").Single();
var uriBackendProcess = new Uri($"{binding.Protocol}://localhost:{binding.Port}");
// This isn't reliable right now because micronetes only guarantees the process starts, not that
// that kestrel started.
@ -122,7 +125,6 @@ namespace E2ETest
var client = new HttpClient(new RetryHandler(handler));
var dashboardUri = new Uri(host.DashboardWebApplication!.Addresses.First());
var dashboardResponse = await client.GetStringAsync(dashboardUri);
await CheckServiceIsUp(host.Application, client, "backend", dashboardUri);
await CheckServiceIsUp(host.Application, client, "frontend", dashboardUri);
@ -162,7 +164,6 @@ namespace E2ETest
var client = new HttpClient(new RetryHandler(handler));
var dashboardUri = new Uri(host.DashboardWebApplication!.Addresses.First());
var dashboardResponse = await client.GetStringAsync(dashboardUri);
await CheckServiceIsUp(host.Application, client, "backend", dashboardUri);
await CheckServiceIsUp(host.Application, client, "frontend", dashboardUri);
@ -176,20 +177,12 @@ namespace E2ETest
private async Task CheckServiceIsUp(Microsoft.Tye.Hosting.Model.Application application, HttpClient client, string serviceName, Uri dashboardUri)
{
// make sure backend is up before frontend
var service = application.Services.Where(a => a.Value.Description.Name == serviceName).First().Value;
var binding = service.Description.Bindings.First();
var protocol = binding.Protocol != null && binding.Protocol.Length != 0 ? binding.Protocol : "http";
var hostName = binding.Host != null && binding.Host.Length != 0 ? binding.Host : "localhost";
var uriString = $"{protocol}://{hostName}:{binding.Port}";
// Confirm that the uri is in the dashboard response.
var dashboardString = await client.GetStringAsync($"{dashboardUri}api/v1/services/{serviceName}");
var uriBackendProcess = new Uri(uriString);
var service = JsonSerializer.Deserialize<V1Service>(dashboardString, _options);
var binding = service.Description!.Bindings.Where(b => b.Protocol == "http").Single();
var uriBackendProcess = new Uri($"{binding.Protocol}://localhost:{binding.Port}");
// This isn't reliable right now because micronetes only guarantees the process starts, not that
// that kestrel started.
try
{
var appResponse = await client.GetAsync(uriBackendProcess);

Loading…
Cancel
Save